| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- #ifndef BB_GC_H
- #define BB_GC_H
- #include "bbstd.h"
- #include "bbtypes.h"
- #include "bbmemory.h"
- #include "bbfunction.h"
- //how much to allocate before a sweep occurs
- //#define BBGC_TRIGGER 0
- //#define BBGC_TRIGGER 64
- //#define BBGC_TRIGGER 256
- //#define BBGC_TRIGGER 65536
- //#define BBGC_TRIGGER 1*1024*1024
- #define BBGC_TRIGGER 4*1024*1024
- //#define BBGC_TRIGGER 16*1024*1024
- //mark while allocating, slower but smoother...
- #define BBGC_INCREMENTAL 1
- //reclaim all memory after a sweep, lumpier...
- //#define BBGC_AGGRESSIVE 1
- //check for use of deleted objects, MUCH leakier...
- //#define BBGC_DEBUG 1
- #if BBGC_DEBUG
- #define BBGC_VALIDATE( P ) \
- if( (P) && (P)->flags==3 ){ \
- printf( "Attempt to use deleted object %p of type '%s'\n",(P),(P)->typeName() ); \
- fflush( stdout ); \
- abort(); \
- }
- #else
- #define BBGC_VALIDATE( P )
- #endif
- struct bbGCNode;
- struct bbGCFiber;
- struct bbGCFrame;
- struct bbGCRoot;
- struct bbGCTmp;
- namespace bbGC{
- extern bbGCRoot *roots;
-
- extern bbGCTmp *freeTmps;
- extern bbGCNode *markQueue;
- extern bbGCNode *unmarkedList;
-
- extern bbGCFiber *fibers;
- extern bbGCFiber *currentFiber;
-
- extern int markedBit;
- extern int unmarkedBit;
-
- void init();
-
- void collect();
-
- bbGCNode *alloc( size_t size );
- }
- struct bbGCNode{
- bbGCNode *succ;
- bbGCNode *pred;
- size_t flags; //0=lonely, 1/2=marked/unmarked; 3=destroyed
- bbGCNode(){
- }
-
- virtual ~bbGCNode(){
- }
- virtual void gcMark(){
- }
-
- virtual void dbEmit(){
- }
-
- virtual const char *typeName()const{
- return "bbGCNode";
- }
- };
- struct bbGCFiber{
- bbGCFiber *succ;
- bbGCFiber *pred;
- bbGCFrame *frames;
- bbGCNode *ctoring;
- bbGCTmp *tmps;
- bbFunction<void()> entry;
-
- bbGCFiber():succ( this ),pred( this ),frames( nullptr ),ctoring( nullptr ),tmps( nullptr ){
- }
-
- void link(){
- succ=bbGC::fibers;
- pred=bbGC::fibers->pred;
- bbGC::fibers->pred=this;
- pred->succ=this;
- }
-
- void unlink(){
- pred->succ=succ;
- succ->pred=pred;
- }
- };
- struct bbGCFrame{
- bbGCFrame *succ;
-
- bbGCFrame():succ( bbGC::currentFiber->frames ){
- bbGC::currentFiber->frames=this;
- }
-
- ~bbGCFrame(){
- bbGC::currentFiber->frames=succ;
- }
- virtual void gcMark(){
- }
- };
- struct bbGCRoot{
- bbGCRoot *succ;
-
- bbGCRoot():succ( bbGC::roots ){
- bbGC::roots=this;
- }
-
- virtual void gcMark(){
- }
- };
- struct bbGCTmp{
- bbGCTmp *succ;
- bbGCNode *node;
- };
- namespace bbGC{
- void retain( bbGCNode *p );
-
- void release( bbGCNode *p );
-
- inline void insert( bbGCNode *p,bbGCNode *succ ){
- p->succ=succ;
- p->pred=succ->pred;
- p->pred->succ=p;
- succ->pred=p;
- }
- inline void remove( bbGCNode *p ){
- p->pred->succ=p->succ;
- p->succ->pred=p->pred;
- }
- inline void enqueue( bbGCNode *p ){
- BBGC_VALIDATE( p )
- if( !p || p->flags!=unmarkedBit ) return;
-
- remove( p );
- p->succ=markQueue;
- markQueue=p;
-
- p->flags=markedBit;
- }
-
- inline void pushTmp( bbGCNode *p ){
- bbGCTmp *tmp=freeTmps;
- if( !tmp ) tmp=new bbGCTmp;
- tmp->node=p;
- tmp->succ=currentFiber->tmps;
- currentFiber->tmps=tmp;
- // puts( "pushTmp" );
- }
-
- inline void popTmps( int n ){
- // printf( "popTmps %i\n",n );
- while( n-- ){
- bbGCTmp *tmp=currentFiber->tmps;
- currentFiber->tmps=tmp->succ;
- tmp->succ=freeTmps;
- freeTmps=tmp;
- }
- }
-
- template<class T> T *tmp( T *p ){
- pushTmp( p );
- return p;
- }
-
- inline void beginCtor( bbGCNode *p ){
- p->succ=currentFiber->ctoring;
- currentFiber->ctoring=p;
- }
-
- inline void endCtor( bbGCNode *p ){
- currentFiber->ctoring=p->succ;
- #if BBGC_INCREMENTAL
- p->succ=markQueue;
- markQueue=p;
- p->flags=markedBit;
- #else
- p->flags=unmarkedBit;
- insert( p,unmarkedList );
- #endif
- }
- }
- template<class T> struct bbGCVar{
- public:
-
- T *_ptr;
-
- void enqueue(){
- #if BBGC_INCREMENTAL
- bbGC::enqueue( dynamic_cast<bbGCNode*>( _ptr ) );
- #endif
- }
-
- bbGCVar():_ptr( nullptr ){
- }
-
- bbGCVar( T *p ):_ptr( p ){
- enqueue();
- }
-
- bbGCVar( const bbGCVar &p ):_ptr( p._ptr ){
- enqueue();
- }
-
- bbGCVar &operator=( T *p ){
- _ptr=p;
- enqueue();
- return *this;
- }
-
- bbGCVar &operator=( const bbGCVar &p ){
- _ptr=p._ptr;
- enqueue();
- return *this;
- }
-
- T *get()const{
- return _ptr;
- }
-
- T *operator->()const{
- return _ptr;
- }
-
- operator T*()const{
- return _ptr;
- }
- };
- template<class T> void bbGCMark( T const& ){
- }
- //inline void bbGCMark(...){
- //}
- template<class T> void bbGCMark( const bbGCVar<T> &v ){
- bbGCMark( v._ptr );
- }
- #endif
|