//回收策略,內存整理和多線程問題暫不考慮
//必要的限制:
//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 <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;
//
#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;
}