CppGC  1.01
gc.h
00001 #ifndef __GC_H__
00002 #define __GC_H__
00003 
00004 #include <stdlib.h>
00005 #include <assert.h>
00006 
00007 #include "threadctx.h"
00008 
00009 namespace GC
00010 {
00011     class Object;
00012     class Root;
00013 
00017     #define GC_MARK(Class) Class(*this)
00018 
00023     struct ObjectHeader 
00024     { 
00025         ObjectHeader* next;
00026 
00027         Object* getObject() const { 
00028             return (Object*)(this + 1);
00029         }
00030     };
00031 
00037     class MemoryAllocator
00038     {
00039         friend class Object;
00040       public:
00044         static MemoryAllocator* getCurrent();
00045 
00050         static void* allocate(size_t size);
00051 
00056         static void mark(Object* obj);
00057 
00063         static void mark(Object** refs, size_t nRefs);
00064 
00068         static void registerRoot(Root* root);
00069             
00073         static void unregisterRoot(Root* root);
00074 
00078         static void gc();
00079 
00083         static void allowGC();
00084         
00091         MemoryAllocator(size_t gcStartThreshold = 1024*1024, size_t gcAutoStartThreshold = (size_t)-1);
00092 
00096         ~MemoryAllocator();
00097     
00098         // internal instance methods
00099         void  _registerRoot(Root* root);     
00100         void  _unregisterRoot(Root* root);        
00101         void  _mark(Object* obj);
00102         void  _mark(Object** refs, size_t nRefs);
00103         void* _allocate(size_t size);
00104         void  _gc();
00105         void  _allowGC();
00106 
00107       private:
00108         void markPhase();
00109         void sweepPhase();
00110 
00111       private:
00112         size_t  allocated;
00113         Root*   roots;
00114         ObjectHeader* objects;
00115         size_t  startThreshold;
00116         size_t  autoStartThreshold;
00117 
00118         static ThreadContext<MemoryAllocator> ctx;
00119     };
00120 
00124     class Object 
00125     {
00126       public:
00130         void* operator new(size_t size) 
00131         { 
00132             return MemoryAllocator::allocate(size);
00133         }
00134 
00138         void* operator new(size_t fixedSize, size_t varyingSize)
00139         { 
00140             return MemoryAllocator::allocate(fixedSize + varyingSize);
00141         }
00142 
00147         void operator delete(void* obj) {
00148             free((ObjectHeader*)obj - 1); 
00149         } 
00150         void operator delete(void* obj, size_t) { 
00151             free((ObjectHeader*)obj - 1);             
00152         } 
00153 
00154       protected:
00155         friend class MemoryAllocator;
00156         
00160         virtual void mark(MemoryAllocator* allocator) {}
00161 
00165         virtual~Object() {}
00166 
00167         ObjectHeader* getHeader() { 
00168             return (ObjectHeader*)this - 1;
00169         }
00170     };
00171 
00177     template<class T>
00178     class Ref 
00179     {
00180         T* obj;
00181 
00182       public:
00183         T& operator*() { 
00184             return *obj;
00185         }
00186         T const& operator*() const { 
00187             return *obj;
00188         }
00189         T* operator->() { 
00190             return obj; 
00191         }
00192         T const* operator->() const { 
00193             return obj; 
00194         }
00195         operator T*() { 
00196             return obj;
00197         }
00198         operator T const*() const { 
00199             return obj;
00200         }
00201         T* operator = (T const* val) {
00202             return obj = (T*)val;            
00203         }
00204         bool operator == (T const* other) { 
00205             return obj == other;
00206         }
00207         bool operator == (Ref<T> const& other) { 
00208             return obj == other.obj;
00209         }
00210         bool operator != (T const* other) { 
00211             return obj != other;
00212         }
00213         bool operator != (Ref<T> const& other) { 
00214             return obj != other.obj;
00215         }
00216         
00217         Ref(T const* ptr = NULL) : obj((T*)ptr) {}
00218 
00222         Ref(Ref<T> const& ref) : obj(ref.obj) {
00223             MemoryAllocator::mark(obj);
00224         }
00225     };
00226 
00230     class Root
00231     {
00232         friend class MemoryAllocator;
00233 
00234       protected:
00235         Root* next; // roots are linked in L1 list
00236         
00241         virtual void mark(MemoryAllocator* allocator) = 0;
00242 
00246         Root() 
00247         { 
00248             MemoryAllocator::registerRoot(this);
00249         }
00250         
00254         ~Root() 
00255         { 
00256             MemoryAllocator::unregisterRoot(this);
00257         }        
00258     };
00259 
00267     template<class T>
00268     class Var : Root
00269     {
00270         T* obj;
00271 
00272       public:
00273         T& operator*() { 
00274             return *obj;
00275         }
00276         T const& operator*() const { 
00277             return *obj;
00278         }
00279         T* operator->() { 
00280             return obj; 
00281         }
00282         T const* operator->() const { 
00283             return obj; 
00284         }
00285         operator T*() { 
00286             return obj;
00287         }
00288         operator T const*() const { 
00289             return obj;
00290         }
00291         T* operator = (T const* val) {
00292             obj = (T*)val;
00293             return val;
00294         }
00295         bool operator == (T const* other) { 
00296             return obj == other;
00297         }
00298         bool operator == (Var<T> const& other) { 
00299             return obj == other.obj;
00300         }
00301         bool operator != (T const* other) { 
00302             return obj != other;
00303         }
00304         bool operator != (Var<T> const& other) { 
00305             return obj != other.obj;
00306         }
00307         
00308         virtual void mark(MemoryAllocator* allocator) { 
00309             allocator->_mark(obj);
00310         }
00311 
00312         Var(T* ptr = NULL) : obj(ptr) {}
00313 
00314         Var(Var<T> const& var) : obj(var.obj) {}
00315     };
00316     
00320     template<class T, size_t size>
00321     class ArrayVar : Root
00322     {
00323         T* array[size];
00324 
00325       public:
00326         T*& operator[](size_t index) 
00327         { 
00328             assert(index < size);
00329             return array[index];
00330         }
00331         
00332         T* operator[](size_t index) const
00333         { 
00334             assert(index < size);
00335             return array[index];
00336         }        
00337 
00338         ArrayVar() {
00339             for (size_t i = 0; i < size; i++) { 
00340                 array[i] = NULL;
00341             }
00342         }
00343 
00344         virtual void mark(MemoryAllocator* allocator) { 
00345             allocator->_mark((Object**)array, size);
00346         }
00347     };
00348 
00352     template<class T>
00353     class VectorVar : Root
00354     {
00355         T** array;
00356         size_t used;
00357         size_t allocated;
00358 
00359       public:
00360         T*& operator[](size_t index) 
00361         { 
00362             assert(index < used);
00363             return array[index];
00364         }
00365         
00366         T* operator[](size_t index) const
00367         { 
00368             assert(index < used);
00369             return array[index];
00370         }        
00371 
00372         size_t size() const
00373         {
00374             return used;
00375         }
00376 
00377         void resize(size_t newSize) 
00378         { 
00379             size_t i;
00380             if (newSize > allocated) { 
00381                 allocated = allocated*2 > newSize ? allocated*2 : newSize;
00382                 T** newArray = new T*[allocated];
00383                 for (i = 0; i < used; i++) { 
00384                     newArray[i] = array[i];
00385                 }
00386                 delete[] array;
00387                 array = newArray;
00388             }
00389             for (i = used; i < newSize; i++) { 
00390                 array[i] = NULL;
00391             }
00392             used = newSize;
00393         }
00394 
00395         void push(T const* obj) { 
00396             resize(used+1);
00397             array[used-1] = (T*)obj;
00398         }
00399 
00400         T* pop() { 
00401             assert(used != 0);
00402             return array[--used];
00403         }
00404 
00405         T* top() const { 
00406             assert(used != 0);
00407             return array[used-1];
00408         }
00409 
00410         VectorVar(size_t reserve = 8) {
00411             used = 0;
00412             allocated = reserve;
00413             array = new T*[reserve];
00414         }
00415 
00416         ~VectorVar() {
00417             delete[] array;
00418         }
00419 
00420         virtual void mark(MemoryAllocator* allocator) { 
00421             allocator->_mark((Object**)array, used);
00422         }
00423     };
00424 };    
00425 
00426 #endif
00427