GC實現

//垃圾回收設想
//回收策略,內存整理和多線程問題暫不考慮

//必要的限制:
//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;
}


發佈了31 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章