[project @ chth@gmx.net-20060624024510-17b61a029bc9d94f]
[acogc.git] / lib / acogc.h
blobf60301d57d13f5c04bf72b71d472d6fcccefa163
1 /*
2 acogc.h - simple accurate/cooperative garbage collector
4 Copyright (C) 2006, Christian Thaeter <chth@gmx.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, contact me.
20 #ifndef ACOGC_H
21 #define ACOGC_H
24 accurate
25 only real references are used for marking objects instead scanning all objects
27 cooperative
28 the programmer has to supply functions which mark references in his datastructures
32 #include <stdlib.h>
33 #include <stdint.h>
34 #include <valgrind/valgrind.h>
35 #include "llist.h"
37 #ifdef EBUG_ACOGC /* CFLAGS+=-DEBUG_ACOGC */
38 #include <assert.h>
39 #include <stdio.h>
40 #include <string.h>
41 #define ACOGC_TRACE(lvl,fmt,...) do{if(lvl<=EBUG_ACOGC)VALGRIND_PRINTF("%s@%d %s " fmt, strrchr(__FILE__, '/')?strrchr(__FILE__, '/') + 1 : __FILE__,__LINE__, __func__ , ## __VA_ARGS__);}while(0)
42 #define ACOGC_ASSERT(expr,fmt,...) do{if(!(expr)){VALGRIND_PRINTF_BACKTRACE("%s " fmt, #expr, ## __VA_ARGS__);abort();}}while(0)
44 #ifdef __GNUC__
45 #define ACOGC_CLEANUP(fn) __attribute__((cleanup(fn)))
46 #endif
48 #else
49 #define ACOGC_TRACE(fmt,...) do{}while(0)
50 #define ACOGC_ASSERT(expr,fmt,...) do{}while(0)
51 #endif
53 #ifdef __GNUC__
54 #define ACOGC_CLEANUP(fn) __attribute__((cleanup(fn)))
55 #endif
58 object types and handles
60 #define ACOGC_DECLARE(name,Handle) \
61 struct acogc_##name##_struct; \
62 typedef struct acogc_##name##_struct acogc_##name;\
63 typedef const acogc_##name * const_Acogc##Handle;\
64 typedef acogc_##name * Acogc##Handle;\
65 typedef acogc_##name ** Acogc##Handle##_ref;\
66 typedef const acogc_##name ** const_Acogc##Handle##_ref
68 //ACOGC_DECLARE(marker,Marker);
69 ACOGC_DECLARE(factory,Factory);
70 ACOGC_DECLARE(object,Object);
71 ACOGC_DECLARE(weakreference,WeakReference);
74 function types
77 //typedef void (*acogc_initize_func)(void*, size_t);
80 the user needs to provide custom scan functions for his objects,
81 ?TODO? returning !0 normally but 1 if the object should not be marked (unmarked)
83 typedef void (*acogc_scan_func)(void* obj);
84 typedef void (*acogc_finalize_func)(void*);
88 enumerations
90 enum acogc_emergency_level
92 ACOGC_COLLECT_DONTFREE, /* just collect, do not free */
93 ACOGC_COLLECT_NORMAL, /* normal collection */
94 ACOGC_COLLECT_FORCELOW, /* free down to lowwater in this factory */
95 ACOGC_COLLECT_ALLFORCELOW, /* free down to lowwater in all factories */
96 ACOGC_COLLECT_FREEABLE, /* free all freeable objects in this factory */
97 ACOGC_COLLECT_ALLFREEABLE, /* free all freeable objects in all factories */
98 ACOGC_COLLECT_FAILED /* can' reclaim any memory */
101 enum acogc_flags
103 ACOGC_FLAG_UNINITIALIZED = 0x0, // allocated but not yet initialized object (keeps GC locked, becomes black)
104 /* the interpretation of colors cycles through 3 states 001 010 100 starting with ecru == 001 followed by white and black */
105 ACOGC_COLOR_1 = 0x1, // 001
106 ACOGC_COLOR_2 = 0x2, // 010
107 ACOGC_COLOR_3 = 0x4, // 100
108 /* next some values are reserved for special purposes where flags > 0x4 */
109 ACOGC_FLAG_ROOT_COLLECTABLE = 0x5, // 101
110 ACOGC_FLAG_ROOT_STATIC = 0x6, // 110
111 ACOGC_FLAG_RESERVED = 0x7 // 111 unused for now
115 manual allocation not garbagge collected, needs to be acogc_free()'d
116 the advantage of these are that malloc will initiate a garbagge collection
117 if no memory is available and call the registered nomemhandler.
118 This functions are guranteed to be interchangeable with malloc/realloc/free as
119 long the pointer doesn't hold a reference, see below.
121 as special feature a address can be setref'ed to another address,
122 the lowest bit is used to indicate this. So only aligned addresses are
123 allowed for this. use the acogc_deref() function to mask it out.
127 unfortunally C doesn't require to align string literals, which is needed when you use the reference feature.
128 This can be enforced with this macro.
130 #ifdef __GNUC__
131 #define ACOGC_ALIGNED_STRING(string) (const char*)&((char __attribute__((aligned(sizeof(int))))[sizeof(string)]){string})
132 #else // fallback for other compilers
133 #define ACOGC_ALIGNED_STRING(string) (const char*)(&((struct {int nil; char str [sizeof(string)];}){0,string}.str))
134 #endif
137 try to (re-)allocate some block of memory with a new size
138 *addr has to be initialized to NULL
139 trying to reallocate a reference is illegal.
141 void
142 acogc_alloc_ (void ** addr, size_t size, AcogcFactory factory);
143 #define acogc_alloc(addr, size, root) acogc_alloc_ ((void**)addr, size, root)
146 realloc a memory block to at least needed size, min 16 bytes, increased by a 1.5 factor on resizing
147 return the amount really reserved
148 when resizing is finsished one might fixate it by calling acogc_alloc with the real required size at last,
149 some realloc implementations might free some memory thereafter.
151 size_t
152 acogc_reserve_ (void ** addr, size_t actual, size_t needed, AcogcFactory factory);
153 #define acogc_reserve(addr, actual, needed, root) acogc_reserve_ ((void**)addr, actual, needed, root)
156 free *addr if not a reference and set it to NULL
158 void
159 acogc_free_ (void ** addr);
160 #define acogc_free(addr) acogc_free_ ((void**)addr)
163 set addr as reference to ref
165 static inline void
166 acogc_set_ref_ (void ** addr, const void * ref)
168 *addr = ref?(void*) (((uintptr_t)ref) | 1):NULL;
170 #define acogc_set_ref(addr, ref) acogc_set_ref_ ((void**)addr, ref)
174 just return the real address value from a possible reference
176 static inline void *
177 acogc_ref_get_ (void * addr)
179 return (void*) (((uintptr_t)addr) & ~(uintptr_t)1);
181 #define acogc_ref_get(addr) (typeof(addr)) acogc_ref_get_ ((void*)addr)
183 static inline int
184 acogc_is_ref (void * addr)
186 return (int)(((uintptr_t)addr) & 1);
190 // TODO cleanup check does not work
191 #define ACOGC_ROOT_REGISTER(name, marker, gcroot, data) \
192 acogc_marker name##_acogc_marker \
193 ACOGC_CLEANUP (acogc_marker_assert_unregistered_root) \
194 = {NULL, marker, &name, data}; \
195 acogc_root_register_marker (gcroot, &name##_acogc_marker)
197 #define ACOGC_ROOT_UNREGISTER(name, gcroot) \
198 acogc_root_marker_unregister (gcroot, &name##_acogc_marker)
201 factory
203 factories are manage classes of memory objects, there are 2 modes in which these factories can operate:
205 first the factory holds the static size for all objects it manages. objects are allocated with 'acogc_factory_alloc'. In this mode swept objects are cached and freed based on the high_water/low_water values. objects can be reinstantiated and the user can implement fancy caching schemes.
207 second when the 'size' is initialized to 0, dynamic sized objects will be allocated with 'acogc_factory_alloc_size', the swept-queue will not be used for allocations
211 adaptive auto configuration:
213 ideally a collection (all grey nodes scanned) should be finish just before the freelist
214 gets empty this would give the optimal memory utilization.
216 If it finishes earlier the time spend in incremental collecting was not ideally distributed which has a small performance impact or there are too much free objects available for the required working set.
218 if the collection is not complete when the freelist becomes empty we have to force a scan if the GC is not locked to get a new freelist or allocate new objects despite there may be enough potential free objects which we cant use yet.
220 So the goal is to optimize the scan_freq in a way that the collection completes before the freelist becomes empty and avoid cases where the collection takes to long.
224 struct acogc_factory_struct
226 llist factories;
228 llist bottom;
229 LList top;
230 LList scan;
231 LList free;
233 llist roots;
234 LList scanned_roots;
236 int gc_lock; // if >0 then dont flip (collector locked)
237 int ecru_color; // 001 010 100 .. current value which tags ecru
239 /* configuration */
240 unsigned scan_freq; // scan every this actions (alloc or touch)
241 unsigned scan_at_once; // scan this much elements in a scan-round
243 /* statistics counters */
244 unsigned scan_counter; // decremented from scan_freq to 0 to initiate a scan an then reset
245 unsigned objects_allocated; // how many objects are in this factory
246 unsigned objects_black; // how many objects are marked black (in use when the collection is complete)
247 unsigned objects_white; // how many objects are marked free
249 unsigned scanned; // count scanned objects
250 signed idle; // increment for scan attempts after collection completed,
251 // decrement for each allocation when the collection is not yet complete
253 /* statistics state */
254 unsigned scan_freq_avg; // cumulating average of the scan freq
255 signed idle_avg; // count scan attempts after collection completed
257 unsigned free_limit; /* keep at most free_limit% objects free else start really freeing objects */
258 unsigned object_cluster; /* this many objects are allocated or freed at once */
260 size_t size; /* 0 for dynamic sized factory */
262 acogc_finalize_func finalize_func; /* called when a object is freed or reused (but not reinstantiated) */
263 acogc_scan_func scan_func; /* called when a object is marked */
264 //void * touch_data; /* supplemental user data passed to touch */
265 //void (*nomemhandler)(void); /* called when no memory can be allocated, defaults to abort() */
269 initialize a acogc_factory
270 when size==0 this factory will be used for dynamic sized allocations
271 the user must supply a custom mark function which calls acogc_object_mark for all (nonweak) references within his object
273 AcogcFactory
274 acogc_factory_new (AcogcFactory other,
275 size_t size,
276 unsigned free_limit,
277 unsigned object_cluster,
278 acogc_scan_func scan,
279 acogc_finalize_func finalize);
281 void
282 acogc_factory_erase (AcogcFactory self);
284 void
285 acogc_factory_free (AcogcFactory self);
287 void
288 acogc_factory_init (AcogcFactory self,
289 AcogcFactory other,
290 size_t size,
291 unsigned free_limit,
292 unsigned object_cluster,
293 acogc_scan_func scan,
294 acogc_finalize_func finalize);
297 //void * mark_data);
300 /* alloc memory from factory with predefined size */
301 void *
302 acogc_factory_alloc (AcogcFactory self);
304 // TODO macro for ensuring a acogc_object_initialized?
306 /* free() swept objects, normally called automatically by the collector */
307 //void
308 //acogc_factory_collectfree (AcogcFactory self, enum acogc_emergency_level elvl);
311 void
312 acogc_factory_scan (AcogcFactory self);
314 void
315 acogc_factory_flip (AcogcFactory self);
320 object
322 a acogc_object prepends each user allocated block
324 struct acogc_object_struct
326 llist objects;
327 AcogcFactory factory; /* last bits are used as flags */
328 AcogcWeakReference weakrefs;
331 // rotate last 3 bits left
332 static inline unsigned
333 acogc_flags_rol_ (unsigned x)
335 return x==4?1:x+x;
338 // rotate last 3 bits right
339 static inline unsigned
340 acogc_flags_ror_ (unsigned x)
342 return x==1?4:x>>1;
345 static inline AcogcObject
346 acogc_object_from_memory_ (void * object)
348 return (AcogcObject)(object - sizeof (acogc_object));
351 static inline void *
352 acogc_memory_from_object_ (AcogcObject object)
354 return (void*)object + sizeof (acogc_object);
357 static inline AcogcObject
358 acogc_object_from_list_ (LList object)
360 return LLIST_TO_STRUCTP (object, acogc_object, objects);
363 static inline void *
364 acogc_memory_from_list_ (LList object)
366 return acogc_memory_from_object_ (LLIST_TO_STRUCTP (object, acogc_object, objects));
369 static inline AcogcFactory
370 acogc_object_factory_get_ (AcogcObject object)
372 return (AcogcFactory)((uintptr_t)(object->factory) & (uintptr_t)~0x7);
375 static inline unsigned
376 acogc_object_flags_get_ (AcogcObject object)
378 return (unsigned)((uintptr_t)(object->factory) & (uintptr_t)0x7);
381 static inline void
382 acogc_object_set_factory_flags_ (AcogcObject object, AcogcFactory factory, const unsigned flags)
384 object->factory = (AcogcFactory)((uintptr_t)factory | (uintptr_t)flags);
387 static inline void
388 acogc_object_set_flags_ (AcogcObject object, const unsigned flags)
390 uintptr_t f = (uintptr_t)object->factory & (uintptr_t)~0x7;
391 object->factory = (AcogcFactory)(f | (uintptr_t)flags);
394 static inline unsigned
395 acogc_object_factory_ecru_ (AcogcObject object)
397 return acogc_object_factory_get_ (object)->ecru_color;
400 static inline unsigned
401 acogc_object_factory_white_ (AcogcObject object)
403 return acogc_flags_ror_ (acogc_object_factory_ecru_ (object));
406 static inline unsigned
407 acogc_object_factory_black_ (AcogcObject object)
409 return acogc_flags_rol_ (acogc_object_factory_ecru_ (object));
412 /* implements a read barrier */
413 void
414 acogc_object_touch_really_ (AcogcObject object);
416 static inline void
417 acogc_object_touch (void* object)
419 AcogcObject o = acogc_object_from_memory_ (object);
420 if (acogc_object_flags_get_ (o) == acogc_object_factory_ecru_ (o))
421 acogc_object_touch_really_ (o);
424 static inline void
425 acogc_object_initialized (void* object)
427 AcogcObject o = acogc_object_from_memory_ (object);
428 ACOGC_ASSERT (acogc_object_flags_get_ (o) == ACOGC_FLAG_UNINITIALIZED, "object is not uninitialized");
429 acogc_object_set_flags_ (o, acogc_object_factory_black_ (o));
430 --acogc_object_factory_get_ (o)->gc_lock;
434 /* register a object as GC root object, should be done as soon as possible after allocation */
435 void
436 acogc_object_addroot (void* object);
438 /* unregister a GC root object, it becomes normal collectable by this. */
439 void
440 acogc_object_removeroot (void* object);
446 references
448 weak references are lists which must be maintained by the programmer
450 struct acogc_weakreference_struct
452 AcogcWeakReference next;
453 void * ref;
456 static inline void
457 acogc_weakreference_init (AcogcWeakReference self)
459 self->next = self->ref = NULL;
463 intrusive weak references:
464 objects which allow weak references to them need to implement a
466 AcogcReference member; head of a linked list, initialized to NULL
468 when the object is collected one must use acogc_reference_weak_invalidate with this pointer to invalidate all weak refs. This can be done in sweep_finalizer or in free_finalizer. It becomes possible that weak references point to dead, not yet freed objects one should then use acogc_object_reinstantiate to make the object life again and establish a some normal reference to this object, else it will be collected soon again and become dead.
470 A weak reference is of type acogc_reference with both members initialized to NULL
472 a weak reference is set up with acogc_reference_link_weak and one must not forget to acogc_reference_weak_unlink before the reference object gets deleted
475 void
476 acogc_weakreference_link (AcogcWeakReference self, void* object);
478 void
479 acogc_weakreference_unlink (AcogcWeakReference self);
481 void
482 acogc_object_weakreference_invalidate (void* object);
486 when a object is swept but still not freed it can be reinstatiated (for example if a weak-reference points to it)
489 /* dereference a weak reference, reinstantiate it if required */
490 void *
491 acogc_weakreference_reinstget (AcogcWeakReference self);
493 /* dereference a weak reference, do not reinstantiate it, return NULL if in freelist */
494 void *
495 acogc_weakreference_get (AcogcWeakReference self);
498 //enum acogc_reference_state
499 //acogc_reference_state (AcogcWeakReference self);
501 void
502 acogc_reference_assert_cleared (AcogcWeakReference p);
504 /* declare a weak reference als automatic variable, asserts that the reference gets unlinked when the stackframe is left (-DEBUG_ACOGC on gcc only) */
505 #define ACOGC_WEAKREFERENCE(name) acogc_weakreference name ACOGC_CLEANUP(acogc_weakreference_assert_cleared) = {NULL, NULL}
507 #define ACOGC_REFERENCE_INIT(name) acogc_weakreference name ACOGC_CLEANUP(acogc_weakreference_assert_cleared) = {NULL, NULL}
510 #endif
512 // Local Variables:
513 // mode: C
514 // c-file-style: "gnu"
515 // End:
516 // arch-tag: 855b7025-8227-4892-ac25-9b0a3d57dd0b
517 // end_of_file