├── depends ├── Makefile ├── license └── bsd_license.txt ├── source ├── CollectorMarker.c ├── CollectorMarker_inline.h ├── Collector_inline.h ├── CollectorMarker.h ├── Collector.h └── Collector.c ├── .gitignore ├── README.md ├── Makefile.lib └── docs └── index.html /depends: -------------------------------------------------------------------------------- 1 | basekit -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include ./Makefile.lib 2 | CFLAGS += -DBUILDING_COLLECTOR_DLL $(IOVMALLFLAGS) 3 | -------------------------------------------------------------------------------- /license/bsd_license.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevedekorte/garbagecollector/HEAD/license/bsd_license.txt -------------------------------------------------------------------------------- /source/CollectorMarker.c: -------------------------------------------------------------------------------- 1 | #define COLLECTORMARKER_C 2 | #include "CollectorMarker.h" 3 | #undef COLLECTORMARKER_C 4 | 5 | #include 6 | 7 | void CollectorMarker_check(CollectorMarker *self) 8 | { 9 | CollectorMarker *v = self; 10 | 11 | while (v != self) 12 | { 13 | assert(v->next->prev == v); 14 | assert(v->prev->next == v); 15 | v = v->next; 16 | } 17 | } 18 | 19 | CollectorMarker *CollectorMarker_new(void) 20 | { 21 | CollectorMarker *self = io_calloc(1, sizeof(CollectorMarker)); 22 | return self; 23 | } 24 | 25 | CollectorMarker *CollectorMarker_newWithColor_(unsigned int color) 26 | { 27 | CollectorMarker *self = CollectorMarker_new(); 28 | self->color = color; 29 | return self; 30 | } 31 | 32 | void CollectorMarker_free(CollectorMarker *self) 33 | { 34 | io_free(self); 35 | } 36 | 37 | void CollectorMarker_loop(CollectorMarker *self) 38 | { 39 | self->prev = self; 40 | self->next = self; 41 | } 42 | 43 | int CollectorMarker_count(CollectorMarker *self) 44 | { 45 | int count = 0; 46 | CollectorMarker *v = self->next; 47 | unsigned int c = self->color; 48 | 49 | while (v->color == c) 50 | { 51 | CollectorMarker *next = v->next; 52 | v = next; 53 | count ++; 54 | } 55 | 56 | return count; 57 | } 58 | 59 | int CollectorMarker_colorSetIsEmpty(CollectorMarker *self) 60 | { 61 | return self->color != self->next->color; 62 | } 63 | 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.lib 2 | *.dll 3 | *.manifest 4 | *.obj 5 | *.exp 6 | *.ilk 7 | ._* 8 | *.pdb 9 | *.hi 10 | *.o 11 | *.so 12 | *.dylib 13 | *.cmd 14 | .mod.c* 15 | *.tmp_versions 16 | *CVS 17 | *RCS 18 | *IoVMCode.c* 19 | *Io*Init.c* 20 | ~* 21 | *_darcs 22 | *_build 23 | *_ioCodeProcessed 24 | *errors 25 | *.bak* 26 | *.BAK* 27 | *.orig* 28 | *vssver.scc* 29 | *.swp* 30 | *MT 31 | *\{arch\} 32 | *.arch-ids 33 | *, 34 | *.class* 35 | *.prof* 36 | *.DS_Store* 37 | *.FBCLockFolder 38 | *BitKeeper 39 | *ChangeSet 40 | *.svn 41 | .cvsignore* 42 | .gdb_history* 43 | *Thumbs.db* 44 | .DS_Store 45 | .libs 46 | .deps* 47 | *.a 48 | *.la 49 | *.lo 50 | *.so 51 | *.dylib 52 | *.exe 53 | *.Po 54 | *.Tlo 55 | *.Plo 56 | _objs 57 | _includes 58 | *_libs 59 | *Io.*Code.c* 60 | io2c 61 | *Io.*Init.c* 62 | *pngtest* 63 | *steve.model* 64 | *skipdbtest* 65 | *config.log* 66 | *config.status* 67 | .rej* 68 | *autom4te.cache* 69 | *.cache 70 | *_include 71 | *tags* 72 | ./addons/SGML/source/libsgml/Makefile* 73 | ./addons/SGML/source/libsgml/examples/Makefile* 74 | ./addons/SGML/source/libsgml/src/Makefile* 75 | tools/editlib_test/editlib_test 76 | extras/IoPlayers/MSWindows/ioplayer/ioplayer.ncb 77 | extras/IoPlayers/MSWindows/ioplayer/ioplayer.suo 78 | extras/IoPlayers/MSWindows/ioplayer/ioplayer/Debug 79 | extras/IoPlayers/MSWindows/ioplayer/ioplayer/Release 80 | extras/IoPlayers/MSWindows/ioplayer/ioplayer/ioplayer.vcproj.CUSTOMER2007.Customer.user 81 | extras/IoPlayers/MSWindows/ioplayer/pingme.txt 82 | extras/IoPlayers/MSWindows/ioplayer/smysrv 83 | libs/iovm/docs/docs.txt 84 | addons/*/docs/docs.txt 85 | *.mode1 86 | *.pbxuser 87 | -------------------------------------------------------------------------------- /source/CollectorMarker_inline.h: -------------------------------------------------------------------------------- 1 | //metadoc CollectorMarker copyright Steve Dekorte 2002 2 | //metadoc CollectorMarker license BSD revised 3 | 4 | #ifdef COLLECTORMARKER_C 5 | #define IO_IN_C_FILE 6 | #endif 7 | #include "Common_inline.h" 8 | #ifdef IO_DECLARE_INLINES 9 | 10 | IOINLINE void CollectorMarker_clear(CollectorMarker *self) 11 | { 12 | self->prev = NULL; 13 | self->next = NULL; 14 | } 15 | 16 | IOINLINE void CollectorMarker_insertAfter_(CollectorMarker *self, CollectorMarker *other) 17 | { 18 | self->color = other->color; 19 | 20 | self->prev = other; 21 | self->next = other->next; 22 | 23 | other->next->prev = self; 24 | other->next = self; 25 | } 26 | 27 | /* 28 | IOINLINE void CollectorMarker_insertBefore_(CollectorMarker *self, CollectorMarker *other) 29 | { 30 | self->color = other->color; 31 | 32 | self->prev = other->prev; 33 | self->next = other; 34 | 35 | other->prev->next = self; 36 | other->prev = self; 37 | } 38 | */ 39 | 40 | IOINLINE void CollectorMarker_remove(CollectorMarker *self) 41 | { 42 | self->prev->next = self->next; 43 | self->next->prev = self->prev; 44 | //self->next = NULL; // temp 45 | //self->prev = NULL; // temp 46 | } 47 | 48 | IOINLINE void CollectorMarker_removeAndInsertAfter_(CollectorMarker *self, CollectorMarker *other) 49 | { 50 | CollectorMarker_remove(self); 51 | CollectorMarker_insertAfter_(self, other); 52 | } 53 | 54 | /* 55 | IOINLINE void CollectorMarker_removeAndInsertBefore_(CollectorMarker *self, CollectorMarker *other) 56 | { 57 | CollectorMarker_remove(self); 58 | CollectorMarker_insertBefore_(self, other); 59 | } 60 | */ 61 | 62 | IOINLINE void CollectorMarker_removeIfNeededAndInsertAfter_(CollectorMarker *self, CollectorMarker *other) 63 | { 64 | if (self->prev) 65 | { 66 | CollectorMarker_remove(self); 67 | } 68 | 69 | CollectorMarker_insertAfter_(self, other); 70 | } 71 | 72 | IOINLINE int CollectorMarker_isEmpty(CollectorMarker *self) 73 | { 74 | return (self->color != self->next->color); 75 | } 76 | 77 | #undef IO_IN_C_FILE 78 | #endif 79 | -------------------------------------------------------------------------------- /source/Collector_inline.h: -------------------------------------------------------------------------------- 1 | //metadoc Collector copyright Steve Dekorte 2002 2 | //metadoc Collector license BSD revised 3 | 4 | #ifdef COLLECTOR_C 5 | #define IO_IN_C_FILE 6 | #endif 7 | #include "Common_inline.h" 8 | #ifdef IO_DECLARE_INLINES 9 | 10 | // inspecting markers ------------------- 11 | 12 | IOINLINE int Collector_markerIsWhite_(Collector *self, CollectorMarker *m) 13 | { 14 | return (self->whites->color == m->color); 15 | } 16 | 17 | IOINLINE int Collector_markerIsGray_(Collector *self, CollectorMarker *m) 18 | { 19 | return (COLLECTOR_GRAY == m->color); 20 | } 21 | 22 | IOINLINE int Collector_markerIsBlack_(Collector *self, CollectorMarker *m) 23 | { 24 | return (self->blacks->color == m->color); 25 | } 26 | 27 | // changing marker colors ------------------- 28 | 29 | IOINLINE void Collector_makeFree_(Collector *self, CollectorMarker *v) 30 | { 31 | #ifdef COLLECTOR_RECYCLE_FREED 32 | CollectorMarker_removeAndInsertAfter_((CollectorMarker *)v, self->freed); 33 | #else 34 | CollectorMarker_remove(v); 35 | CollectorMarker_free(v); 36 | #endif 37 | } 38 | 39 | IOINLINE void Collector_makeWhite_(Collector *self, CollectorMarker *v) 40 | { 41 | CollectorMarker_removeAndInsertAfter_((CollectorMarker *)v, self->whites); 42 | } 43 | 44 | IOINLINE void Collector_makeGray_(Collector *self, CollectorMarker *v) 45 | { 46 | CollectorMarker_removeAndInsertAfter_((CollectorMarker *)v, self->grays); 47 | } 48 | 49 | IOINLINE void Collector_makeBlack_(Collector *self, CollectorMarker *v) 50 | { 51 | CollectorMarker_removeAndInsertAfter_((CollectorMarker *)v, self->blacks); 52 | } 53 | 54 | IOINLINE void Collector_makeGrayIfWhite_(Collector *self, void *v) 55 | { 56 | if (Collector_markerIsWhite_(self, (CollectorMarker *)v)) 57 | { 58 | Collector_makeGray_(self, (CollectorMarker *) v); 59 | } 60 | } 61 | 62 | /* 63 | IOINLINE void Collector_makeFreed_(Collector *self, void *v) 64 | { 65 | CollectorMarker_removeAndInsertAfter_(v, self->freed); 66 | } 67 | */ 68 | #ifdef COLLECTOR_USE_NONINCREMENTAL_MARK_SWEEP 69 | 70 | #define Collector_value_addingRefTo_(self, v, ref) 71 | 72 | #else 73 | 74 | IOINLINE void *Collector_value_addingRefTo_(Collector *self, void *v, void *ref) 75 | { 76 | if (Collector_markerIsBlack_(self, (CollectorMarker *)v) && Collector_markerIsWhite_(self, (CollectorMarker *)ref)) 77 | //if (self->safeMode || (Collector_markerIsBlack_(self, (CollectorMarker *)v) && Collector_markerIsWhite_(self, (CollectorMarker *)ref))) 78 | { 79 | Collector_makeGray_(self, (CollectorMarker *) ref); 80 | } 81 | 82 | return ref; 83 | } 84 | 85 | #endif 86 | 87 | #undef IO_IN_C_FILE 88 | #endif 89 | -------------------------------------------------------------------------------- /source/CollectorMarker.h: -------------------------------------------------------------------------------- 1 | 2 | //metadoc CollectorMarker copyright Steve Dekorte 2002 3 | //metadoc CollectorMarker license BSD revised 4 | 5 | #ifndef COLLECTORMARKER_DEFINED 6 | #define COLLECTORMARKER_DEFINED 1 7 | 8 | #include "Common.h" 9 | #include "List.h" 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | #if !defined(__MINGW32__) && defined(WIN32) 16 | #if defined(BUILDING_COLLECTOR_DLL) || defined(BUILDING_IOVMALL_DLL) 17 | #define COLLECTOR_API __declspec(dllexport) 18 | #else 19 | #define COLLECTOR_API __declspec(dllimport) 20 | #endif 21 | 22 | #else 23 | #define COLLECTOR_API 24 | #endif 25 | 26 | typedef void (CollectorDoFunc)(void *); 27 | 28 | typedef struct CollectorMarker CollectorMarker; 29 | 30 | #define CollectorMarkerSansPointer \ 31 | CollectorMarker *prev; \ 32 | CollectorMarker *next; \ 33 | unsigned int color : 2; \ 34 | unsigned int hash1; \ 35 | unsigned int hash2; 36 | 37 | /* 38 | #if !defined(COLLECTOROBJECTTYPE) 39 | #define COLLECTOROBJECTTYPE void 40 | #endif 41 | */ 42 | 43 | typedef struct IoObjectData IoObjectData; 44 | #define IoObjectDataDefined 1 45 | 46 | struct CollectorMarker 47 | { 48 | CollectorMarkerSansPointer 49 | IoObjectData *object; 50 | }; 51 | 52 | #define COLLECTOR_REF_TYPE(Type) \ 53 | typedef struct \ 54 | { \ 55 | CollectorMarkerSansPointer; \ 56 | Type *object; \ 57 | } Type ## Ref; 58 | 59 | #define CollectorMarker_setObject_(self, v) ((CollectorMarker *)self)->object = v; 60 | #define CollectorMarker_object(self) (((CollectorMarker *)self)->object) 61 | 62 | COLLECTOR_API CollectorMarker *CollectorMarker_new(void); 63 | 64 | CollectorMarker *CollectorMarker_newWithColor_(unsigned int color); 65 | COLLECTOR_API void CollectorMarker_free(CollectorMarker *self); 66 | 67 | void CollectorMarker_loop(CollectorMarker *self); 68 | void CollectorMarker_check(CollectorMarker *self); 69 | 70 | //void CollectorMarker_removeAndInsertAfter_(CollectorMarker *self, CollectorMarker *other); 71 | void CollectorMarker_removeAndInsertBefore_(CollectorMarker *self, CollectorMarker *other); 72 | //void CollectorMarker_removeIfNeededAndInsertAfter_(CollectorMarker *self, CollectorMarker *other); 73 | 74 | //void CollectorMarker_remove(CollectorMarker *self); 75 | int CollectorMarker_count(CollectorMarker *self); 76 | int CollectorMarker_colorSetIsEmpty(CollectorMarker *self); 77 | 78 | #define CollectorMarker_setColor_(self, c) ((CollectorMarker *)self)->color = c; 79 | #define CollectorMarker_color(self) ((CollectorMarker *)self)->color; 80 | 81 | #define CollectorMarker_num(self) (((CollectorMarker *)self)->num); 82 | #define CollectorMarker_setNext_(self, v) ((CollectorMarker *)self)->next = v; 83 | #define CollectorMarker_setPrev_(self, v) ((CollectorMarker *)self)->prev = v; 84 | 85 | #define MARKER(v) ((CollectorMarker *)v) 86 | 87 | #define COLLECTMARKER_FOREACH(self, v, code) \ 88 | { \ 89 | CollectorMarker *v = self->next; \ 90 | CollectorMarker *_next; \ 91 | unsigned int c = self->color; \ 92 | \ 93 | while (v->color == c) \ 94 | { \ 95 | _next = v->next; \ 96 | code; \ 97 | v = _next; \ 98 | } \ 99 | } 100 | 101 | #include "CollectorMarker_inline.h" 102 | 103 | #ifdef __cplusplus 104 | } 105 | #endif 106 | #endif 107 | -------------------------------------------------------------------------------- /source/Collector.h: -------------------------------------------------------------------------------- 1 | //metadoc Collector copyright Steve Dekorte, 2006 2 | //metadoc Collector license BSD revised 3 | //metadoc Collector description A tricolor collector using a Baker treadmill. 4 | 5 | #ifndef Collector_DEFINED 6 | #define Collector_DEFINED 1 7 | 8 | #include "CollectorMarker.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #define COLLECTOR_FOREACH(self, v, code) \ 15 | COLLECTMARKER_FOREACH(self->whites, v, code;); \ 16 | COLLECTMARKER_FOREACH(self->grays, v, code;); \ 17 | COLLECTMARKER_FOREACH(self->blacks, v, code;); 18 | 19 | //#define COLLECTOR_RECYCLE_FREED 1 20 | #define COLLECTOR_USE_NONINCREMENTAL_MARK_SWEEP 1 21 | 22 | typedef enum 23 | { 24 | COLLECTOR_INITIAL_WHITE, 25 | COLLECTOR_GRAY, 26 | COLLECTOR_INITIAL_BLACK, 27 | COLLECTOR_FREE 28 | } CollectorColor; 29 | 30 | typedef int (CollectorMarkFunc)(void *); 31 | typedef void (CollectorWillFreeFunc)(void *); 32 | typedef void (CollectorFreeFunc)(void *); 33 | typedef int (CollectorCheckFunc)(void *); 34 | 35 | typedef struct 36 | { 37 | List *retainedValues; 38 | void *markBeforeSweepValue; 39 | 40 | int pauseCount; 41 | 42 | CollectorMarker *blacks; 43 | CollectorMarker *grays; 44 | CollectorMarker *whites; 45 | CollectorMarker *freed; 46 | 47 | float marksPerAlloc; 48 | float queuedMarks; 49 | 50 | size_t allocated; 51 | size_t allocatedSweepLevel; 52 | float allocatedStep; 53 | 54 | CollectorMarkFunc *markFunc; 55 | CollectorWillFreeFunc *willFreeFunc; 56 | CollectorFreeFunc *freeFunc; 57 | 58 | long clocksUsed; 59 | size_t sweepCount; 60 | int debugOn; 61 | int safeMode; 62 | 63 | #ifdef COLLECTOR_USE_NONINCREMENTAL_MARK_SWEEP 64 | int newMarkerCount; 65 | #endif 66 | } Collector; 67 | 68 | COLLECTOR_API Collector *Collector_new(void); 69 | COLLECTOR_API void Collector_free(Collector *self); 70 | 71 | COLLECTOR_API void Collector_check(Collector *self); 72 | COLLECTOR_API void Collector_checkObjectPointers(Collector *self); // if not 0, then memory is hosed 73 | COLLECTOR_API void Collector_checkObjectsWith_(Collector *self, CollectorCheckFunc *func); 74 | 75 | COLLECTOR_API void Collector_setMarkBeforeSweepValue_(Collector *self, void *v); 76 | 77 | // callbacks 78 | 79 | COLLECTOR_API void Collector_setMarkFunc_(Collector *self, CollectorMarkFunc *func); 80 | COLLECTOR_API void Collector_setWillFreeFunc_(Collector *self, CollectorWillFreeFunc *func); 81 | COLLECTOR_API void Collector_setFreeFunc_(Collector *self, CollectorFreeFunc *func); 82 | 83 | // marks per alloc 84 | 85 | COLLECTOR_API void Collector_setMarksPerAlloc_(Collector *self, float n); 86 | COLLECTOR_API float Collector_marksPerAlloc(Collector *self); 87 | 88 | // marks per sweep 89 | 90 | COLLECTOR_API void Collector_setAllocatedStep_(Collector *self, float n); 91 | COLLECTOR_API float Collector_allocatedStep(Collector *self); 92 | 93 | // debug 94 | 95 | COLLECTOR_API void Collector_setDebug_(Collector *self, int b); 96 | COLLECTOR_API void Collector_setSafeModeOn_(Collector *self, int b); 97 | 98 | // retaining 99 | 100 | COLLECTOR_API void *Collector_retain_(Collector *self, void *v); 101 | COLLECTOR_API void Collector_stopRetaining_(Collector *self, void *v); 102 | COLLECTOR_API void Collector_removeAllRetainedValues(Collector *self); 103 | 104 | // adding 105 | 106 | COLLECTOR_API CollectorMarker *Collector_newMarker(Collector *self); 107 | COLLECTOR_API void Collector_addValue_(Collector *self, void *v); 108 | 109 | // collection 110 | 111 | COLLECTOR_API void Collector_initPhase(Collector *self); 112 | COLLECTOR_API size_t Collector_sweep(Collector *self); 113 | COLLECTOR_API size_t Collector_sweepPhase(Collector *self); 114 | COLLECTOR_API void Collector_markPhase(Collector *self); 115 | 116 | COLLECTOR_API size_t Collector_collect(Collector *self); 117 | COLLECTOR_API size_t Collector_freeAllValues(Collector *self); 118 | 119 | // changing colors 120 | 121 | #define Collector_shouldMark_(self, v) Collector_makeGrayIfWhite_(self, v) 122 | //void Collector_makeGrayIfWhite_(Collector *self, void *v); 123 | 124 | //void Collector_makeWhite_(Collector *self, CollectorMarker *v); 125 | //void Collector_makeGray_(Collector *self, CollectorMarker *v); 126 | //void Collector_makeBlack_(Collector *self, CollectorMarker *v); 127 | 128 | //int Collector_markerIsWhite_(Collector *self, CollectorMarker *m); 129 | //int Collector_markerIsGray_(Collector *self, CollectorMarker *m); 130 | //int Collector_markerIsBlack_(Collector *self, CollectorMarker *m); 131 | 132 | COLLECTOR_API char *Collector_colorNameFor_(Collector *self, void *v); 133 | 134 | //void *Collector_value_addingRefTo_(Collector *self, void *v, void *ref); 135 | 136 | // pause/resume stack 137 | 138 | COLLECTOR_API void Collector_pushPause(Collector *self); 139 | COLLECTOR_API void Collector_popPause(Collector *self); 140 | COLLECTOR_API int Collector_isPaused(Collector *self); 141 | COLLECTOR_API double Collector_timeUsed(Collector *self); 142 | 143 | 144 | #include "Collector_inline.h" 145 | 146 | #ifdef __cplusplus 147 | } 148 | #endif 149 | #endif 150 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # garbagecollector 2 | 3 | ## Overview 4 | 5 | libgarbagecollector is an incremental tricolor tracing collector using a Baker Treadmill. libgarbagecollector is not an allocator; it only keeps track of the objects you tell it about and determines when it is safe to free them. So you'll allocate objects using malloc() (or the allocator of your choice), and register them with the collector. When the collector finds that an object can be freed, it will call a function you give it to do the actual deallocation. 6 | 7 | ## Getting Started 8 | 9 | First you'll need to create a collector instance: 10 | 11 | Collector *collector = Collector_new(); 12 | 13 | 14 | Your values must contain the CollectorMarker struct as the first part of it's structure. So their struct declarations will look something like this: 15 | 16 | struct MyObjectType 17 | { 18 | CollectorMarker marker; 19 | ... 20 | }; 21 | 22 | 23 | The collector manages the CollectorMarker and your code shouldn't touch it. 24 | 25 | To tell the collector about your root value(s), call: 26 | 27 | Collector_retain_(collector, aRootValue) 28 | 29 | 30 | ## Adding Values 31 | 32 | When you allocate an object, you add the value to the collector. 33 | 34 | Collector_addValue_(collector, aValue) 35 | 36 | 37 | ## Marking 38 | 39 | You provide the means for the collector to trace the reference graph via the mark callback function. 40 | 41 | Collector_setMarkFunc_(collector, MyObjectType_mark); 42 | 43 | 44 | In your object's mark function, you'll need to call: 45 | 46 | Collector_shouldMark_(collector, referencedValue); 47 | 48 | 49 | on each of the values it references. 50 | 51 | You also need to tell the collector when a reference is added from one object to another (this is typically called the write barrier) and is required to support incremental collection. 52 | 53 | Collector_value_addingRefTo_(collector, value, referencedValue); 54 | 55 | 56 | ## Freeing 57 | 58 | Every so many Collector_addValue_() calls, the collector will do a bit of marking, and every so many marks it will do a sweep. A sweep will result in the free callback being called for each value that was found to be unreachable. 59 | 60 | You'll need to set the free callback to tell the collector which function to call when a value is found to be no longer reachable: 61 | 62 | Collector_setFreeFunc_(collector, MyObjectType_free) 63 | 64 | 65 | ## Atomic Operations 66 | 67 | When you're doing an atomic operation, like initializing a new object, it's important to call: 68 | 69 | Collector_pushPause(collector); 70 | 71 | 72 | To resume the collector, call: 73 | 74 | Collector_popPause(collector); 75 | 76 | 77 | These increment and decrement a pause count and the collector will delay any marking until the pause count is zero. 78 | 79 | ## Stacks 80 | 81 | Since the structure of the C stack is unknown, there is no way to trace it. By "stack" here I mean value stacks which hold the values being referenced by the C stack (or referenced by your language locals, if your language's stack frames aren't first class). 82 | 83 | The simplest way to deal with stacks is to call: 84 | 85 | Collector_value_addingRefTo_(collector, stackOwnerValue, newStackValue); 86 | 87 | 88 | whenever a new value is added to the stack. This will ensure that things referenced by the stack get marked. The next 2 sections describe how to ensure the stacks themselves get marked. 89 | 90 | ### Cooperative Multitasking Stacks 91 | 92 | In the case of my programming language, Io, coroutines are used for concurrency and are first class objects in the language. 93 | 94 | So if a coroutine is reachable via the root node, it will get marked and if not, no one will be able to tell it to resume, so it's safe to collect it. This works for all coroutines except the main coroutine (the one that started the program) and the current coroutine. So on startup I call: 95 | 96 | Collector_retain_(collector, mainCoroutineValue); 97 | 98 | 99 | to ensure the main coroutine won't be collected. And everytime Io resumes a coroutine, I call: 100 | 101 | Collector_setMarkBeforeSweepValue_(collector, currentCoroutineValue); 102 | 103 | 104 | Which will cause currentCoroutineValue to get marked immediately before the collector enters a sweep phase. 105 | 106 | ### Premptive Multitasking Stacks 107 | 108 | If your language uses premtive threads which cannot be collected until they are explicitly exited, then you'll need to call: 109 | 110 | Collector_retain_(collector, threadObjectValue); 111 | 112 | 113 | when a thread begins and: 114 | 115 | Collector_stopRetaining_(collector, threadObjectValue); 116 | 117 | 118 | when it ends. The retained values are stored in an array, so this is bit inefficient if you're dealing with thousands of threads that are frequently created and destroyed, but for the typical case (10s of threads with greater than one second lifetimes) it should work well. 119 | 120 | ## Globals 121 | 122 | Globals such as language primitives that should not be collected until shutdown can avoid being collected by calling: 123 | 124 | Collector_retain_(collector, someGlobalValue); 125 | 126 | 127 | on each global. 128 | 129 | ## Options 130 | 131 | The collection parameters can be adjusted with these methods: 132 | 133 | Collector_setAllocsPerMark_(collector, apm); 134 | Collector_setMarksPerSweep_(collector, mps); 135 | Collector_setSweepsPerGeneration_(collector, spg); 136 | 137 | 138 | ## Cleaning Up 139 | 140 | To free all values beign monitored by the collector, call: 141 | 142 | 143 | Collector_freeAllValues(collector); 144 | 145 | 146 | To free your collector instance, call: 147 | 148 | Collector_free(collector); 149 | 150 | 151 | ## Notes 152 | 153 | No attempt has been made to make this code safe for use when it's functions are called from multiple prememtive threads simultaniously. 154 | -------------------------------------------------------------------------------- /Makefile.lib: -------------------------------------------------------------------------------- 1 | ifeq ($(shell [ -f Makefile.local ] && echo true),true) 2 | ALL_BEGIN := $(MAKE) -f Makefile.local all_begin 3 | ALL_END := $(MAKE) -f Makefile.local all_end 4 | MAKE_LOCAL_CLEAN := $(MAKE) -f Makefile.local clean 5 | else 6 | ALL_BEGIN := 7 | ALL_END := 8 | MAKE_LOCAL_CLEAN := 9 | endif 10 | 11 | #CC ?= g++ 12 | 13 | RANLIB ?= ranlib 14 | AR ?= ar 15 | ARFLAGS := rcu 16 | AROUTFLAG := 17 | CCOUTFLAG := -o 18 | LINKDLL := $(CC) 19 | LINKDLLOUTFLAG := -o 20 | LINKDIRFLAG := -L 21 | LINKLIBFLAG := -l 22 | INSTALL_PREFIX_DEFINE := $(INSTALL_PREFIX) 23 | 24 | # may need to remove --param max-inline-insns-single=500 for older versions of gccs 25 | WARN :=-Wstrict-prototypes 26 | #-Winline 27 | #--param max-inline-insns-single=500 28 | 29 | #-ansi -pedantic 30 | OPTIMIZE :=-O3 -g 31 | #-msse2 -msse -mmmx 32 | #OPTIMIZE :=-O3 -ffast-math -ftree-vectorize -ftree-vectorizer-verbose=4 33 | DLL_SUFFIX := so 34 | DLL_COMMAND := -shared 35 | FLAT_NAMESPACE := 36 | dependson := $(shell cat depends) 37 | 38 | HEADERS :=-I. -I./source 39 | others := $(dependson) 40 | others := $(addprefix -I../,$(others)) 41 | others := $(addsuffix /_build/headers,$(others)) 42 | HEADERS += $(others) 43 | 44 | DLL_L := $(dependson) 45 | DLL_L := $(addprefix -L../,$(DLL_L)) 46 | DLL_L := $(addsuffix /_build/dll,$(DLL_L)) 47 | 48 | DLL_l := $(dependson) 49 | DLL_l := $(addprefix -l,$(DLL_l)) 50 | 51 | CFLAGS = $(OPTIMIZE) $(WARN) $(HEADERS) #--param max-inline-insns-single=500 52 | 53 | # Uncommment for Coros to register their stack with Valgrind 54 | #CFLAGS += -DUSE_VALGRIND 55 | 56 | ### PLATFORM ##################################################### 57 | 58 | SYS ?= $(shell uname -s) 59 | 60 | ifeq ($(SYS),Darwin) 61 | CFLAGS += -falign-loops=16 62 | CFLAGS += -fPIC 63 | DLL_SUFFIX := dylib 64 | DLL_COMMAND := -dynamiclib 65 | FLAT_NAMESPACE := -flat_namespace 66 | endif 67 | 68 | ifeq ($(SYS),DragonFly) 69 | LFLAGS += -lm 70 | endif 71 | 72 | ifeq ($(SYS),Linux) 73 | CFLAGS += -falign-loops=16 74 | CFLAGS += -fPIC 75 | endif 76 | 77 | ifeq ($(SYS),IRIX) 78 | RANLIB ?= touch 79 | endif 80 | 81 | ifneq (,$(findstring CYGW,$(SYS))) 82 | DLL_SUFFIX := dll 83 | endif 84 | 85 | ifneq (,$(findstring MINGW,$(SYS))) 86 | DLL_SUFFIX := dll 87 | endif 88 | 89 | ifneq (,$(findstring Windows,$(SYS))) 90 | CC := cl -nologo 91 | CCOUTFLAG :=-Fo 92 | WARN := 93 | #OPTIMIZE :=-Zi -MDd -D_USE_MATH_DEFINES -DWIN32 -D_DEBUG -D_CRT_SECURE_NO_DEPRECATE 94 | OPTIMIZE :=-O2 -EHsc -MD -D_USE_MATH_DEFINES -DWIN32 -DNDEBUG -D_CRT_SECURE_NO_DEPRECATE 95 | AR := link -lib 96 | AROUTFLAG :=-out: 97 | ARFLAGS := 98 | LINKDLL := link 99 | LINKDLLOUTFLAG :=-out: 100 | LINKDIRFLAG := -libpath: 101 | LINKLIBFLAG := 102 | DLL_LIB_SUFFIX := .lib 103 | DLL_LIB_PREFIX := 104 | DLL_COMMAND := -link /INCREMENTAL:NO -subsystem:WINDOWS -machine:X86 -DLL $(DEF_FILE) 105 | DLL_SUFFIX := dll 106 | DLL_EXTRAS := ws2_32.lib shell32.lib 107 | FLAT_NAMESPACE := 108 | RANLIB := echo no ranlib 109 | INSTALL_PREFIX_DEFINE := $(shell cygpath -am $(INSTALL_PREFIX)) 110 | endif 111 | 112 | ### FILES ######################################################### 113 | 114 | NAME := $(notdir $(subst $() ,_,$(shell pwd))) 115 | LIBR := _build/lib/lib$(NAME).a 116 | DLL := _build/dll/lib$(NAME).$(DLL_SUFFIX) 117 | infiles := $(wildcard source/*.c) 118 | #infiles += $(wildcard *.S) 119 | asmfiles := $(wildcard source/*.S) 120 | hfiles := $(wildcard source/*.h) 121 | buildhfiles := $(subst source/,_build/headers/,$(hfiles)) 122 | objects := $(notdir $(infiles)) 123 | objects := $(basename $(objects)) 124 | objects := $(addsuffix .o,$(objects)) 125 | objects := $(addprefix _build/objs/,$(objects)) 126 | 127 | vmall_objects := $(notdir $(infiles)) 128 | vmall_objects := $(basename $(vmall_objects)) 129 | vmall_objects := $(addsuffix .o,$(vmall_objects)) 130 | vmall_objects := $(addprefix _build/vmall_objs/,$(vmall_objects)) 131 | 132 | 133 | DLL_L := $(dependson) 134 | DLL_L := $(addprefix $(LINKDIRFLAG)../,$(DLL_L)) 135 | DLL_L := $(addsuffix /_build/dll,$(DLL_L)) 136 | 137 | DLL_l := $(dependson) 138 | DLL_l := $(addprefix $(LINKLIBFLAG),$(DLL_l)) 139 | DLL_l := $(addsuffix $(DLL_LIB_SUFFIX),$(DLL_l)) 140 | 141 | DEF_FILE := 142 | 143 | ### RULES ########################################################### 144 | 145 | all: _build/objs _build/headers _build/lib _build/dll $(buildhfiles) 146 | $(ALL_BEGIN) 147 | $(MAKE) $(LIBR) 148 | $(MAKE) $(DLL) 149 | ifneq (,$(findstring Windows,$(SYS))) 150 | mkdir -p _build/vmall_objs 151 | $(MAKE) vmall_objs 152 | endif 153 | $(ALL_END) 154 | 155 | _build: 156 | mkdir -p $@ 157 | 158 | _build/objs: _build 159 | mkdir -p $@ 160 | 161 | _build/headers: _build 162 | mkdir -p $@ 163 | 164 | _build/lib: _build 165 | mkdir -p $@ 166 | 167 | _build/dll: _build 168 | mkdir -p $@ 169 | 170 | # pull in dependency info for *existing* .o files 171 | -include $(objects:.o=.d) 172 | 173 | _build/objs/%.o: source/%.c 174 | ifeq (,$(findstring Windows,$(SYS))) 175 | $(CC) -MM -MT $@ -MF $(@:.o=.d) -DINSTALL_PREFIX=\"$(INSTALL_PREFIX_DEFINE)\" $(CFLAGS) -c $< $(CCOUTFLAG)$@ 176 | endif 177 | $(CC) -DINSTALL_PREFIX=\"$(INSTALL_PREFIX_DEFINE)\" $(CFLAGS) -c $< $(CCOUTFLAG)$@ 178 | 179 | _build/vmall_objs/%.o: source/%.c 180 | $(CC) -DINSTALL_PREFIX=\"$(INSTALL_PREFIX_DEFINE)\" $(CFLAGS) \ 181 | -DBUILDING_IOVMALL_DLL -c $< $(CCOUTFLAG)$@ 182 | 183 | _build/headers/%.h: source/%.h _build/headers 184 | cp $< $@ 185 | 186 | _build/vmall_objs: 187 | mkdir -p $@ 188 | 189 | vmall_objs: _build/vmall_objs $(vmall_objects) 190 | 191 | $(LIBR): $(objects) 192 | ifneq ($(asmfiles),) 193 | $(CC) $(CFLAGS) -c $(asmfiles) $(CCOUTFLAG)_build/objs/asm.o || true 194 | endif 195 | $(AR) $(ARFLAGS) $(AROUTFLAG)$@ _build/objs/*.o 196 | $(RANLIB) $@ 197 | 198 | $(DLL): $(objects) 199 | $(LINKDLL) $(DLL_COMMAND) $(FLAT_NAMESPACE) $(DLL_L) _build/objs/*.o $(LINKDLLOUTFLAG)$(DLL) $(DLL_l) $(DLL_EXTRAS) 200 | ifneq (,$(findstring Windows,$(SYS))) 201 | mt.exe -manifest $@.manifest -outputresource:$@ 202 | rm $@.manifest 203 | endif 204 | 205 | clean: 206 | rm -rf _build 207 | $(MAKE_LOCAL_CLEAN) 208 | 209 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |