|
CppGC
1.01
|
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
1.7.6.1