靈巧指標與垃圾回收原始碼 (轉)

worldblog發表於2007-12-12
靈巧指標與垃圾回收原始碼 (轉)[@more@]

  本人將貼上於此,各位有興趣的網友可以測試一試。

說明:

  只要將兩個加入到你的工程中,並在你的CWinApp派生類中加入如下一句即可:

  CPtrManager thePtrManager;

  然後,在使用普通指標的地方,用靈巧指標替換即可,假如有一個類test,並有如下應用:

  test * ptest=new test;

  other  code

  delete ptest;

現在可這樣應用:

  auto_ptr ptest= new test;

  other code

再不用人為的delete  ptest 了,垃圾回收將自動清除,即使你有如下應用:

  auto_ptr  ptest;

  test  mytest;

  ptest=&mytest;

你也不用擔心,靈巧指標也不會誤刪你在棧中的。

  只要大家認真幫我測試這段程式碼到沒有 ,並對部分演算法進行和改進,那麼,我可以相信:“C++中無垃圾回收”將成為歷史。

 

// PtrManager.h: interface for the CPtrManager class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PTRMANAGER_H__BB4B38B5_DA34_11D3_9327_000629377185__INCLUDED_)
#define AFX_PTRMANAGER_H__BB4B38B5_DA34_11D3_9327_000629377185__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Afxmt.h"

class CMySingleLock:public CSingleLock
{
public:
 CMySingleLock(CSync* pObject, BOOL bInitialLock = FALSE )
 :CSingleLock(pObject,bInitialLock){}
  void operator delete(void * p)
 {
  free(p);
 }
  void * operator new(size_t size)
 { 
  return malloc(size);
 }
};


class CPtr
{
 friend class CMark;
public:
 int GetPtrSize();
 CMutex * GetCMutex();
 void * GetPtr();
 CPtr();
 virtual ~CPtr();
 int GetCount();
  void AddAutoPtr(void * autoPtr,int AutoMark);
 BOOL DeleteAutoPtr(void * autoPtr);
 void SetPtr(void * thePtr,int Size,
  int mark,int count=0);
 
  void operator delete(void * p)
 {
  free(p);
 }
  void * operator new(size_t size)
 { 
  return malloc(size);
 }

private:
 int m_mark;
 int m_count;
 void * m_ptr;
 int m_size;
 CPtrArray AutoPtrArray;
 CUIntArray m_AutoMark; in the stack; >0 =mark
 CMutex mutex;
};

class CMark
{
 friend class CMarkTable;
public:
 CMark(){}
 virtual ~CMark(){}


  void operator delete(void * p)
 {
  free(p);
 }
  void * operator new(size_t size)
 { 
  return malloc(size);
 }
 void CopyFromCPtr(CPtr* theCPtr);
 BOOL bIsNoneInStack();
 void Release();
private:
 int m_mark;
 CPtrArray autoptrArray;
 CUIntArray automarkArray;

};
class CMarkTable
{
public:
 CMarkTable(){Init();}
 virtual ~CMarkTable(){}
 
 void AddCMark(CMark * theCMark);
 BOOL FindMark(int mark);
 void Init();
 void DoLockMark();
private:
 CPtrArray CMarkArray;
 CPtrArray CLockMarkArray;
 void GetLockMark();
 BOOL FindLockMark(int mark);
 void RemoveUnlockMark();
 void RemoveGroup(int automark);

};

 


class CPtrManager 
{
public:
 int GetAutoMark(void * ptr);
 CPtrManager();
 virtual ~CPtrManager();
 int GetMarkFromPtr(void * Ptr);
 void *MallocPtr(size_t size);
  BOOL bCanWrite();
 void DeletePtr(int mark,void * Ptr);
 void AddPtr(void *Ptr,int PtrSize);
 static CPtrManager * GetPtrManager();
 CPtr * GetCPtr(void * Ptr,int mark);

private:
  CPtrArray m_ptr;
 void*  pCurrent;
 unsigned int m_mark;
 CUIntArray m_removed;
 BOOL bWrite;
 static CPtrManager * p_this;
 CMutex mutex;
 CMarkTable myMarkTable;
 void RemoveLockRes();
 void CopyAllMark();
 static UINT myThreadProc(LPVOID lparm);
 CWinThread* myThread;
 void BeginThread()
 { myThread=AfxBeginThread(myThreadProc,this);}
};

class parent_autoptr
{
public:
 parent_autoptr()
 {thisAutoMark=0;}
 virtual ~parent_autoptr(){}
 virtual void Release(){}
protected:
 int thisAutoMark;
};

template
class auto_ptr :public parent_autoptr
{
  public:
  virtual void Release(){Remove();}
  auto_ptr()
  {mark=0;pointee=0;thisAutoMark=GetAutoMark();}
  auto_ptr(auto_ptr&rhs);
  auto_ptr(T*ptr);
  ~auto_ptr(){Remove();}
  T*operator->() const;
  operator T*();
  T&operator*()const;
  auto_ptr&operator=(auto_ptr&rhs);
  auto_ptr&operator=(T*ptr);
  private:
  void Remove();
  int GetAutoMark();
  CMutex *GetCMutex();
  void ReadyWrite();
  T*pointee;
  int mark;
 
};
template T* auto_ptr< T>::operator ->()const
{
 return pointee;
}
template void auto_ptr< T>::ReadyWrite()
{
 CPtrManager * pMana=CPtrManager::GetPtrManager();
  if(pMana)
 {
 for(;;)
 {
 if(pMana->bCanWrite())
 break;
 }
 }
}
template int auto_ptr< T>::GetAutoMark()
{
 CPtrManager * pMana=CPtrManager::GetPtrManager();
  if(pMana)
 {
 return pMana->GetAutoMark(this);
 }
 return 0;
}
template CMutex* auto_ptr< T>::GetCMutex()
{
  CPtrManager * pMana=CPtrManager::GetPtrManager();
  if(pMana)
  {
  CPtr * theCPtr=pMana->GetCPtr(pointee,mark);
  if(theCPtr)
  return theCPtr->GetCMutex();
  }
  return NULL;
}
template void auto_ptr< T>::Remove()
{
CMutex * theMutex=GetCMutex();
if(theMutex)
{
 CMySingleLock *pLock=new CMySingleLock(theMutex);
 pLock->Lock();
 BOOL bDeleteLock=FALSE;
 
  CPtrManager * pMana=CPtrManager::GetPtrManager();
 if(pointee&&pMana)
 {
  CPtr * theCPtr=pMana->GetCPtr(pointee,mark);
  if(theCPtr)
  {
  if(theCPtr->DeleteAutoPtr(this))
  {
  if(theCPtr->GetCount()==0)
  {
  pLock->Unlock();
  delete pLock;
  pMana->DeletePtr(mark,pointee);
  bDeleteLock=TRUE;
  delete pointee;

  }
  }

  } 
  else
  {
  dec to do
  }


 }
 pointee=NULL;
 mark=0;
 if(!bDeleteLock)
 delete pLock;
}
}
template auto_ptr< T>::operator T*()
{
 return pointee;
}
template T& auto_ptr< T>::operator *()const
{
 return *pointee;
}
template auto_ptr< T>::auto_ptr(auto_ptr&rhs)
{
thisAutoMark=GetAutoMark();
ReadyWrite();
CMutex * theMutex=GetCMutex();
if(theMutex)
{
 CSingleLock singleLock(theMutex);
 singleLock.Lock();


 pointee=rhs.pointee;
 mark=rhs.mark;
 CPtrManager * pMana=CPtrManager::GetPtrManager();
 if(pMana)
 {
  CPtr* theCPtr=pMana->GetCPtr(pointee,mark);
  if(theCPtr)
  {
  theCPtr->AddAutoPtr(this,thisAutoMark);
  }

 }

}
template auto_ptr< T>::auto_ptr(T*ptr)
{
  thisAutoMark=GetAutoMark();
  ReadyWrite();

  mark=0;
  pointee=ptr;
  CPtrManager * pMana=CPtrManager::GetPtrManager();
  if(pMana)
  {
  mark=pMana->GetMarkFromPtr(ptr);
  if(mark>0)
  {
 CPtr* theCPtr=pMana->GetCPtr(pointee,mark);
  if(theCPtr)
 {
  CMutex * theMutex=theCPtr->GetCMutex();
  if(theMutex)
  {
   CSingleLock singleLock(theMutex);
  singleLock.Lock();
  theCPtr->AddAutoPtr(this,thisAutoMark);
  }
 }
  }
   
  }
}
templateauto_ptr& auto_ptr< T>::operator=(auto_ptr&rhs)
{
if(pointee!=rhs.pointee)
{
  ReadyWrite();
  Remove();
 
  pointee=rhs.pointee;
  mark=rhs.mark;

  CMutex * theMutex=GetCMutex();
  if(theMutex)
  {
  CSingleLock singleLock(theMutex);
  singleLock.Lock();

  CPtrManager * pMana=CPtrManager::GetPtrManager();
 if(pMana)
 {
  CPtr* theCPtr=pMana->GetCPtr(pointee,mark);
  if(theCPtr)
 {
  theCPtr->AddAutoPtr(this,thisAutoMark);
 }
 }

  }
}
 return *this;

}
template auto_ptr&auto_ptr< T>::operator = (T* ptr)
{
  if(pointee!=ptr)
  {
  ReadyWrite();

  Remove();
  pointee=ptr;
  CPtrManager * pMana=CPtrManager::GetPtrManager();
  if(pMana)
  {

  mark=pMana->GetMarkFromPtr(ptr);
  if(mark>0)
  {
 CPtr* theCPtr=pMana->GetCPtr(pointee,mark);
  if(theCPtr)
 {
   CMutex * theMutex=theCPtr->GetCMutex();
   if(theMutex)
 {
   CSingleLock singleLock(theMutex);
  singleLock.Lock();
  theCPtr->AddAutoPtr(this,thisAutoMark);
 
 }
 }
  }
 
  }
  }
  return *this;
}


class test
{
public:
 auto_ptr p;
};
#endif // !defined(AFX_PTRMANAGER_H__BB4B38B5_DA34_11D3_9327_000629377185__INCLUDED_)

 

 

// PtrManager.cpp: implementation of the CPtrManager class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "PtrManager.h"

CPtrManager * CPtrManager::p_this=0;


void operator delete(void * p)
{
 free(p);
}
void * operator new(size_t size)
{
  CPtrManager * pMana=CPtrManager::GetPtrManager();
 
  return pMana->MallocPtr(size);

}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPtr::CPtr()
{
 m_count=0;
 m_mark=0;
 m_ptr=0;
 m_size=0;
 AutoPtrArray.SetSize(0);
 m_AutoMark.SetSize(0);
}
CPtr::~CPtr()
{
}
void * CPtr::GetPtr()
{
  return m_ptr;
}
void CPtr::AddAutoPtr(void * autoPtr,int AutoMark)
{
 int size=AutoPtrArray.GetSize();
 AutoPtrArray.SetAtGrow(size,autoPtr);
 m_AutoMark.SetAtGrow(size,AutoMark);
 m_count++;
}
BOOL CPtr::DeleteAutoPtr(void * autoPtr)
{
 int size=AutoPtrArray.GetSize();
 for(int i=0;i {
 if(autoPtr==AutoPtrArray[i])
 {
 AutoPtrArray.RemoveAt(i);
 m_AutoMark.RemoveAt(i);
 m_count--;
 return TRUE;
 }
 }
 return FALSE;
}
int CPtr::GetCount()
{
 return m_count;
}
void CPtr::SetPtr(void * thePtr,int Size,int mark,int count)
{
 m_ptr=thePtr;
 m_mark=mark;
  m_size=Size;
 m_count=count;
}
CMutex * CPtr::GetCMutex()
{
  return &mutex;
}
int CPtr::GetPtrSize()
{
return m_size;
}

 

// class CPtrManager

CPtrManager::CPtrManager()
{
  m_mark=0;
  m_ptr.SetSize(1);
  m_ptr[0]=0;
  m_removed.SetSize(0);
  p_this=this;
  pCurrent=0;
  bWrite=TRUE;
  myThread=0;
  BeginThread();
}

CPtrManager::~CPtrManager()
{
  p_this=0;
 if(myThread)
  myThread->SuspendThread( );
 int size=m_ptr.GetSize();
 for(int i=1;i {
 if(m_ptr[i])
 {
 free(m_ptr[i]);
 }
 }

}
void CPtrManager::AddPtr(void *Ptr,int PtrSize)
{
  CSingleLock singleLock(&mutex);
 singleLock.Lock();

 int size=0;
  if(m_removed.GetSize()==0)
 {
  size =m_ptr.GetSize();
 }
  else
 {
   size=m_removed[0];
  m_removed.RemoveAt(0);
 }
 if(size==0)
 size=1;
 CPtr * thePtr=new CPtr;
 thePtr->SetPtr(Ptr,PtrSize,size);
 m_ptr.SetAtGrow(size,thePtr);

 pCurrent=Ptr;
 m_mark=size;
}
void * CPtrManager::MallocPtr(size_t size)
{
  CSingleLock singleLock(&mutex);
  singleLock.Lock();

  void * p=malloc(size);
  if(p)
  AddPtr(p,size);
 
  return p;
}
void CPtrManager::DeletePtr(int mark,void*Ptr)
{

  if(mark<=0||m_ptr.GetSize()  return ;

  CSingleLock singleLock(&mutex);
 singleLock.Lock();

  if(m_ptr[mark])
  {
  CPtr * thePtr=(CPtr*)m_ptr[mark];
  if(Ptr!=thePtr->GetPtr())
  return ;
  delete thePtr;
  m_ptr[mark]=NULL;
  m_removed.Add(mark);
  }

}
int CPtrManager::GetMarkFromPtr(void * Ptr)
{
  CSingleLock singleLock(&mutex);
 singleLock.Lock();

 if(pCurrent==Ptr)
 return m_mark;

 int size=m_ptr.GetSize();
 for(int i=1;i {
 if(m_ptr[i]==Ptr)
 return i;
 }
 return NULL;
}
CPtrManager * CPtrManager::GetPtrManager()
{
 return p_this;
}
BOOL CPtrManager::bCanWrite()
{
 return bWrite;
}
CPtr * CPtrManager::GetCPtr(void * Ptr,int mark)
{

 if(!Ptr||mark<=0 || m_ptr.GetSize() return NULL;

 CSingleLock singleLock(&mutex);
 singleLock.Lock();

 if(m_ptr[mark])
 {
 CPtr * thePtr=(CPtr*)m_ptr[mark];
 if(Ptr!=thePtr->GetPtr())
 return NULL;
 else
 return thePtr;
 }
 return NULL;
}

 


int CPtrManager::GetAutoMark(void *ptr)
{
  CSingleLock singleLock(&mutex);
 singleLock.Lock();

  int size =m_ptr.GetSize();
  for(int i=1;i  {
  CPtr* theCPtr=(CPtr*)m_ptr[i];
  if(theCPtr)
  {
  int ptrFirst=(int)theCPtr->GetPtr();
  int ptrEnd=ptrFirst+theCPtr->GetPtrSize();
  int p=(int)ptr;
  if(p>=ptrFirst&&p<=ptrEnd)
  return  i;
  }
  }
  return 0;
}

void CPtrManager::RemoveLockRes()
{
 CopyAllMark();
 myMarkTable.DoLockMark();
}
void CPtrManager::CopyAllMark()
{
 CSingleLock singleLock(&mutex);
 singleLock.Lock();

 CUIntArray theIntArray;
 theIntArray.SetSize(0);
 int size=m_ptr.GetSize();
 for(int i=0;i {
 theIntArray.SetAtGrow(i,i+1);
 }

 bWrite=FALSE;

  BOOL bALLCopyed=TRUE;
 int TotalWhile=0;
 do
 {
 TotalWhile++;
 bALLCopyed=TRUE;
 size=theIntArray.GetSize();
 for(i=0;i {
 int m=theIntArray[i];
 CPtr * theCPtr=(CPtr*)m_ptr[m];
 if(theCPtr)
 {
 CMutex * theMutex;
 theMutex=theCPtr->GetCMutex();
 if(theMutex)
 {
  CMySingleLock * theLock;
  theLock=new CMySingleLock(theMutex);
  if(!theLock->IsLocked())
  {
  if(theLock->Lock(50))
  {
  CMark * theMark;
  theMark=new CMark();
  theMark->CopyFromCPtr(theCPtr);
  delete theLock;
  myMarkTable.AddCMark(theMark);
  theIntArray.RemoveAt(i);
  i--;
  size--;
  }
  else
  {
  delete theLock;
  bALLCopyed=FALSE;
  }
  }
  else
  {
  delete theLock;
  bALLCopyed=FALSE;
  }
 }
 }
 }
 if(TotalWhile>=50)
 break;
 }while(!bALLCopyed);

  bWrite=TRUE;
}

UINT CPtrManager::myThreadProc(LPVOID lparm)
{
 CPtrManager* pana=(CPtrManager*)lparm;
 if(!pana)
 return 0;
 Sleep(500);
 for(;;)
 pana->RemoveLockRes();
 return 0;

}
class CMark
void CMark::CopyFromCPtr(CPtr *theCPtr)
{
 if(!theCPtr)
 return;
 
 int size=(theCPtr->AutoPtrArray).GetSize();
 automarkArray.SetSize(size);
 autoptrArray.SetSize(size);
 for(int i=0;i {
 automarkArray[i]=(theCPtr->m_AutoMark)[i];
 autoptrArray[i]=(theCPtr->AutoPtrArray)[i];
 }
 m_mark=theCPtr->m_mark;
}

BOOL CMark::bIsNoneInStack()
{
 int size=automarkArray.GetSize();
 if(size==0)
 return FALSE;
 for(int i=0;i {
 if(automarkArray[i]<=0)
 return FALSE;
 }
 return TRUE;
}
void CMark::Release()
{
 int size=autoptrArray.GetSize();
 for(int i=0;i {
 parent_autoptr * thePtr=
 (parent_autoptr *)autoptrArray[i];
 thePtr->Release();
 }
}

Calss CMark 

class CMarkTable

void CMarkTable::AddCMark(CMark * theCMark)
{
 if(theCMark)
  CMarkArray.Add(theCMark);
}
BOOL CMarkTable::FindMark(int mark)
{
 int size=CMarkArray.GetSize();
 for(int i=0;i {
 CMark * theMark=(CMark *)CMarkArray[i];
 if(theMark)
 {
 if(mark==theMark->m_mark)
 return TRUE;
 }
 }
 return FALSE;
}

void CMarkTable::GetLockMark()
{
 CLockMarkArray.SetSize(0);
 int size=CMarkArray.GetSize();
 for(int i=0;i {
 CMark * theMark=(CMark*)CMarkArray[i];
 if(theMark)
 {
 if(theMark->bIsNoneInStack())
 CLockMarkArray.SetAtGrow(i,theMark);
 }
 }
}
void CMarkTable::RemoveUnlockMark()
{
CUIntArray UnlockMarkArray;
BOOL bNoneRemoveed;
do
{
 bNoneRemoveed=TRUE;
 UnlockMarkArray.SetSize(0);
 int size=CLockMarkArray.GetSize();
 for(int i=0;i {
 CMark * theMark=(CMark*)CLockMarkArray[i];
 if(theMark)
 {
 int size1=(theMark->automarkArray).GetSize();

 for(int j=0;j {
 int mark=(theMark->automarkArray)[j];
 if(!FindLockMark(mark))
 {
 UnlockMarkArray.InsertAt(0,i); to remove
 bNoneRemoveed=FALSE;
 break;
 }
 }
 }
 else
 {
 UnlockMarkArray.InsertAt(0,i);
 bNoneRemoveed=FALSE;
 }
 }
 int size2=UnlockMarkArray.GetSize();
 for(int k=0;k {
 int m=UnlockMarkArray[k];
 CLockMarkArray.RemoveAt(m);
 }
}while(!bNoneRemoveed);

}
BOOL CMarkTable::FindLockMark(int mark)
{
 int size=CLockMarkArray.GetSize();
 for(int i=0;i {
 CMark * theMark=(CMark *)CLockMarkArray[i];
 if(theMark)
 {
 if(mark==theMark->m_mark)
 return TRUE;
 }
 }
 return FALSE;
}
void CMarkTable::RemoveGroup(int automark)
{
 int size=CLockMarkArray.GetSize();
 for(int i=0;i {
 CMark * theMark=(CMark *)CLockMarkArray[i];
 if(theMark)
 {
 if(automark==theMark->m_mark)
 {
 CLockMarkArray.RemoveAt(i);
  int size2=
  (theMark->automarkArray).GetSize();
 for(int j=0;j {
 int auto_mark=
 (theMark->automarkArray)[j];
 RemoveGroup(auto_mark);
 }
 break;
 }
 
 }
 }
}
void CMarkTable::DoLockMark()
{
GetLockMark();
RemoveUnlockMark();
int size=CLockMarkArray.GetSize();

while(size)
{
 CMark* theMark=(CMark*)CLockMarkArray[0];
 CLockMarkArray.RemoveAt(0);
 if(theMark)
 {
 int size2=
 (theMark->automarkArray).GetSize();
 for(int i=0;i {
 int automark=
 (theMark->automarkArray)[i];
 RemoveGroup(automark);
 }
 theMark->Release();
 }
 size=CLockMarkArray.GetSize();
}

Init();
}
void CMarkTable::Init()
{
 int size=CMarkArray.GetSize();
 for(int i=0;i {
 CMark* theMark=(CMark*)CMarkArray[i];
 if(theMark)
 delete theMark;
 }
 CMarkArray.SetSize(0);
  CLockMarkArray.SetSize(0);

}
class CMarkTable


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992049/,如需轉載,請註明出處,否則將追究法律責任。

相關文章