本人将源代码粘贴于此,各位有兴趣的网友可以测试一试。
说明:
只要将两个文件加入到你的工程中,并在你的CWinApp派生类中加入如下一句即可:
CPtrManager thePtrManager;
然后,在使用普通指针的地方,用灵巧指针替换即可,假如有一个类test,并有如下应用:
test * ptest=new test;
other code
delete ptest;
现在可这样应用:
auto_ptr<test> ptest= new test;
other code
再不用人为的delete ptest 了,垃圾回收将自动清除,即使你有如下应用:
auto_ptr<test> ptest;
test mytest;
ptest=&mytest;
你也不用担心,灵巧指针也不会误删你在栈中的内存。
只要大家认真帮我测试这段代码到没有 BUG,并对部分算法进行优化和改进,那么,我可以相信:“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(CSyncObject* 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; file://0 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 T> class auto_ptr :public parent_autoptr { public: virtual void Release(){Remove();} auto_ptr() {mark=0;pointee=0;thisAutoMark=GetAutoMark();} auto_ptr(auto_ptr<T>&rhs); auto_ptr(T*ptr); ~auto_ptr(){Remove();} T*operator->() const; operator T*(); T&operator*()const; auto_ptr<T>&operator=(auto_ptr<T>&rhs); auto_ptr<T>&operator=(T*ptr); private: void Remove(); int GetAutoMark(); CMutex *GetCMutex(); void ReadyWrite(); T*pointee; int mark; }; template<class T> T* auto_ptr< T>::operator ->()const { return pointee; } template<class T> void auto_ptr< T>::ReadyWrite() { CPtrManager * pMana=CPtrManager::GetPtrManager(); if(pMana) { for(;;) { if(pMana->bCanWrite()) break; } } } template<class T> int auto_ptr< T>::GetAutoMark() { CPtrManager * pMana=CPtrManager::GetPtrManager(); if(pMana) { return pMana->GetAutoMark(this); } return 0; } template<class T> 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<class T> 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 { file://User decide to do }
} pointee=NULL; mark=0; if(!bDeleteLock) delete pLock; } } template<class T> auto_ptr< T>::operator T*() { return pointee; } template<class T> T& auto_ptr< T>::operator *()const { return *pointee; } template<class T> auto_ptr< T>::auto_ptr(auto_ptr<T>&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<class T> 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); } } } } } template<class T>auto_ptr<T>& auto_ptr< T>::operator=(auto_ptr<T>&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<class T> auto_ptr<T>&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<test> 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<size;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<size;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()<mark+1) 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<size;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()<mark+1) 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<size;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<size-1;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<size;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;
} file://begin 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<size;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<size;i++) { if(automarkArray[i]<=0) return FALSE; } return TRUE; } void CMark::Release() { int size=autoptrArray.GetSize(); for(int i=0;i<size;i++) { parent_autoptr * thePtr= (parent_autoptr *)autoptrArray[i]; thePtr->Release(); } }
file://end Calss CMark
file://begin 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<size;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<size;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<size;i++) { CMark * theMark=(CMark*)CLockMarkArray[i]; if(theMark) { int size1=(theMark->automarkArray).GetSize();
for(int j=0;j<size1;j++) { int mark=(theMark->automarkArray)[j]; if(!FindLockMark(mark)) { UnlockMarkArray.InsertAt(0,i); file://record to remove bNoneRemoveed=FALSE; break; } } } else { UnlockMarkArray.InsertAt(0,i); bNoneRemoveed=FALSE; } } int size2=UnlockMarkArray.GetSize(); for(int k=0;k<size2;k++) { int m=UnlockMarkArray[k]; CLockMarkArray.RemoveAt(m); } }while(!bNoneRemoveed);
} BOOL CMarkTable::FindLockMark(int mark) { int size=CLockMarkArray.GetSize(); for(int i=0;i<size;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<size;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<size2;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<size2;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<size;i++) { CMark* theMark=(CMark*)CMarkArray[i]; if(theMark) delete theMark; } CMarkArray.SetSize(0); CLockMarkArray.SetSize(0);
} file://end class CMarkTable 
|