// 垃圾回收设想 // 回收策略,内存整理和多线程问题暂不考虑 // 必要的限制: // 1、所有具备垃圾回收功能的类都必须派生自gcBase // 2、只能通过gcPtr和gcSPtr来访问gcBase(和派生类), // 也就是说,直接申明gcBase的全局变量和通过原生指针gcBase *都不是合法的 // 使用gcBase的全局变量会导致在垃圾回收代码delete一个无效的内存 // 通过原生指针gcBase *访问gcBase会导致垃圾回收提前删除这个对象 // 3、gcPtr和gcSPtr原则上都必须知道是哪个gcBase拥有它。 // gcSPtr的拥有者设置成一个全局的gcBase的实例,因此,gcSPtr应该在全局变量和栈变量上使用 // 这些限制类似于C++/CLI (vs2005)的垃圾回收 // -------------------------------------------------------------------------------------------------- #pragma warning(disable : 4355) // 垃圾回收策略 struct gcTactic ... { virtual ~gcTactic(); virtual void Check() = 0; static gcTactic * sm_pInstance; static void CheckGarbage() ...{ sm_pInstance->Check(); }} ; struct gcBase; // GC指针基类 struct __gc_Ptr__ ... { friend gcBase;private: gcBase * __gc_m_pParent; __gc_Ptr__ * __gc_m_pNext; __gc_Ptr__ * __gc_m_pPrev; void __InitLink(gcBase * pParent); static void * operator new (size_t); static void operator delete (void *); static void operator delete (void *,size_t);protected: gcBase * __gc_m_pRef;public: ~__gc_Ptr__(); __gc_Ptr__(gcBase * pParent) ...{ __gc_m_pRef = 0; __InitLink(pParent); } __gc_Ptr__(gcBase * pParent,gcBase * __r) ...{ __gc_m_pRef = __r; __InitLink(pParent); } __gc_Ptr__(gcBase * pParent,const __gc_Ptr__ & __r) ...{ __gc_m_pRef = __r.__gc_m_pRef; __InitLink(pParent); } __gc_Ptr__ & operator = (gcBase * __r) ...{ __gc_m_pRef = __r; return *this; } __gc_Ptr__ & operator = (const __gc_Ptr__ & __r) ...{ __gc_m_pRef = __r.__gc_m_pRef; return *this; }} ; // 所有具备垃圾回收功能的类都必须派生自此类 struct gcBase ... { friend __gc_Ptr__;private: static volatile long __gc_sm_nObjectCounter; static size_t __gc_sm_nScanCounter; static gcBase __gc_sm_Root; static gcBase * __gc_sm_pFirst; static void __gc_Mark(gcBase * obj); size_t __gc_m_nScanCounter; __gc_Ptr__ * __gc_m_pFirstPtr; gcBase * __gc_m_pNext; gcBase * __gc_m_pPrev;public: static void GarbageCallback(); gcBase(); virtual ~gcBase();} ; // 当作成员变量的GC指针 template < class _Ty > struct gcPtr : public __gc_Ptr__ ... { typedef _Ty * _Pty; typedef gcPtr<_Ty> this_type; gcPtr(gcBase * pParent) :__gc_Ptr__(pParent) ...{ } gcPtr(gcBase * pParent,_Pty __r) :__gc_Ptr__(pParent,__r) ...{ } gcPtr(gcBase * pParent,const this_type & __r) :__gc_Ptr__(pParent,__r) ...{ } this_type & operator = (_Pty __r) ...{ __gc_m_pRef = __r; if(__gc_m_pRef == NULL) gcTactic::CheckGarbage(); return *this; } this_type & operator = (const this_type & __r) ...{ __gc_m_pRef = __r.__gc_m_pRef; if(__gc_m_pRef == NULL) gcTactic::CheckGarbage(); return *this; } operator _Pty () const...{ return (_Pty)__gc_m_pRef; } _Pty operator -> () const...{ return (_Pty)__gc_m_pRef; } _Pty * operator & ()...{ return (_Pty *)&__gc_m_pRef; } const _Pty * operator & () const...{ return (const _Pty *)&__gc_m_pRef; }} ; // 在栈上使用的GC指针 template < class _Ty > struct gcSPtr : public gcPtr < _Ty > ... { typedef gcPtr<_Ty> base_type; typedef gcSPtr<_Ty> this_type; gcSPtr() :gcPtr<_Ty>(NULL) ...{ } gcSPtr(_Pty __r) :gcPtr(NULL,__r) ...{ } gcSPtr(const base_type & __r) :gcPtr(NULL,__r) ...{ } gcSPtr(const this_type & __r) :gcPtr(NULL,__r) ...{ } ~gcSPtr() ...{ if(__gc_m_pRef != NULL) ...{ __gc_m_pRef = NULL; gcTactic::CheckGarbage(); } } this_type & operator = (_Pty __r) ...{ base_type::operator = (__r); return *this; } this_type & operator = (const base_type & __r) ...{ base_type::operator = (__r); return *this; }} ; // -------------------------------------------------------------------------------------------------- // 另外一种设想————还没有想好 struct __gcHeap__ ... { static __gcHeap__ sm_Heap;} ; #define gc_new new(__gcHeap__::sm_Heap) #include " gcbase.h " #include < windows.h > #ifndef NULL #define NULL 0 #endif struct gcDefaultTactic : public gcTactic ... { volatile long m_bChecking; gcDefaultTactic() ...{ m_bChecking = 0; } virtual ~gcDefaultTactic() ...{ } virtual void Check() ...{ if(m_bChecking) return ; InterlockedExchange(&m_bChecking,1); gcBase::GarbageCallback(); InterlockedExchange(&m_bChecking,0); }} ;gcTactic:: ~ gcTactic() ... {} gcTactic * gcTactic::sm_pInstance = NULL; volatile long gcBase::__gc_sm_nObjectCounter = 0 ;size_t gcBase::__gc_sm_nScanCounter = 1 ;gcBase gcBase::__gc_sm_Root;gcBase * gcBase::__gc_sm_pFirst = NULL; void __gc_Ptr__::__InitLink(gcBase * pParent) ... { if(pParent == NULL) pParent = &gcBase::__gc_sm_Root; __gc_m_pParent = pParent; __gc_m_pNext = __gc_m_pParent->__gc_m_pFirstPtr; __gc_m_pPrev = NULL; if(__gc_m_pNext != NULL) __gc_m_pNext->__gc_m_pPrev = this; __gc_m_pParent->__gc_m_pFirstPtr = this;} __gc_Ptr__:: ~ __gc_Ptr__() ... { if(this == __gc_m_pParent->__gc_m_pFirstPtr) __gc_m_pParent->__gc_m_pFirstPtr = __gc_m_pNext; if(__gc_m_pNext) __gc_m_pNext->__gc_m_pPrev = __gc_m_pPrev; if(__gc_m_pPrev) __gc_m_pPrev->__gc_m_pNext = __gc_m_pNext;} struct __gcFinalGarbageCallback ... { ~__gcFinalGarbageCallback() ...{ gcBase::GarbageCallback(); }} ;gcBase::gcBase() ... { static __gcFinalGarbageCallback __final_gc; static gcDefaultTactic __celue; if(gcDefaultTactic::sm_pInstance == NULL) gcDefaultTactic::sm_pInstance = &__celue; __gc_m_nScanCounter = 0; __gc_m_pFirstPtr = NULL; __gc_m_pNext = __gc_sm_pFirst; __gc_m_pPrev = NULL; if(__gc_m_pNext != NULL) __gc_m_pNext->__gc_m_pPrev = this; __gc_sm_pFirst = this; InterlockedIncrement(&__gc_sm_nObjectCounter);} gcBase:: ~ gcBase() ... { if(this == __gc_sm_pFirst) __gc_sm_pFirst = __gc_m_pNext; if(__gc_m_pNext) __gc_m_pNext->__gc_m_pPrev = __gc_m_pPrev; if(__gc_m_pPrev) __gc_m_pPrev->__gc_m_pNext = __gc_m_pNext; __gc_m_pFirstPtr = NULL; InterlockedDecrement(&__gc_sm_nObjectCounter); gcTactic::CheckGarbage();} void gcBase::__gc_Mark(gcBase * obj) ... { obj->__gc_m_nScanCounter = __gc_sm_nScanCounter; for(__gc_Ptr__ * p = obj->__gc_m_pFirstPtr; p;) ...{ obj = p->__gc_m_pRef; p = p->__gc_m_pNext; if(obj == NULL) continue; __gc_Mark(obj); }} void gcBase::GarbageCallback() ... { ++__gc_sm_nScanCounter; __gc_Mark(&__gc_sm_Root); for(gcBase * p = __gc_sm_pFirst; p; ) ...{ gcBase * temp = p->__gc_m_pNext; if(p->__gc_m_nScanCounter != __gc_sm_nScanCounter) delete p; p = temp; }} // -------------------------------------------------------------------------------------------------- __gcHeap__ __gcHeap__::sm_Heap; // testgc.cpp : 定义控制台应用程序的入口点。 // #include " stdafx.h " #include " gcbase.h " struct BTree : public gcBase ... { gcPtr<BTree> m_pLeft; gcPtr<BTree> m_pRight; int m_nID; BTree(int id) :m_pLeft(this) ,m_pRight(this) ...{ m_nID = id; }} ; void BuildTree( int & id,gcPtr < BTree > & tree, int nDepth) ... { if(nDepth) ...{ tree->m_pLeft = new BTree(id++); BuildTree(id,tree->m_pLeft,nDepth - 1); tree->m_pRight = new BTree(id++); BuildTree(id,tree->m_pRight,nDepth - 1); }} void PrintTree(gcPtr < BTree > & tree) ... { std::cout << tree->m_nID << std::endl; if(tree->m_pLeft != NULL) ...{ PrintTree(tree->m_pLeft); tree->m_pLeft = NULL; } if(tree->m_pRight != NULL) PrintTree(tree->m_pRight);} int _tmain( int argc, _TCHAR * argv[]) ... { //如果有内存泄露,CRT就可以通过VC的输出窗口报告出来 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); int id = 0; gcSPtr<BTree> tree(new BTree(id++)); BuildTree(id,tree,5); PrintTree(tree); gcBase::GarbageCallback(); //这个时候不可能发生垃圾回收 tree = NULL; //所有垃圾都会被回收 return 0;}