I have 2 questions about boehm-gc.
When GC collects garbage-object, GC free memory without calling destructor although the object has destructor. I found GC calls "finailzer", but I don't know how to register it... How can I do?
When GC collect garbage, GC seems not to call free() (or other memory free function). It seems that GC doesn't free garbage, but put it to GC's memory pool and use pool at next allocation. GC frees the memory pool at idle time? If not, can I say to GC "please free memory pool"?
PS. I can't find boehm-gc reference.. Could you tell me where the reference is?
If you need more reference than is provided in the gc.h
header file, then you probably should read up on garbage collectors before going any further.
Re you question, the gc.h
header has what you need:
typedef void (*GC_finalization_proc)
GC_PROTO((GC_PTR obj, GC_PTR client_data));
GC_API void GC_register_finalizer
GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR *ocd));
GC_API void GC_debug_register_finalizer
GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR *ocd));
/* When obj is no longer accessible, invoke */
/* (*fn)(obj, cd). If a and b are inaccessible, and */
/* a points to b (after disappearing links have been */
/* made to disappear), then only a will be */
/* finalized. (If this does not create any new */
/* pointers to b, then b will be finalized after the */
/* next collection.) Any finalizable object that */
/* is reachable from itself by following one or more */
/* pointers will not be finalized (or collected). */
/* Thus cycles involving finalizable objects should */
/* be avoided, or broken by disappearing links. */
/* All but the last finalizer registered for an object */
/* is ignored. */
/* Finalization may be removed by passing 0 as fn. */
/* Finalizers are implicitly unregistered just before */
/* they are invoked. */
/* The old finalizer and client data are stored in */
/* *ofn and *ocd. */
/* Fn is never invoked on an accessible object, */
/* provided hidden pointers are converted to real */
/* pointers only if the allocation lock is held, and */
/* such conversions are not performed by finalization */
/* routines. */
/* If GC_register_finalizer is aborted as a result of */
/* a signal, the object may be left with no */
/* finalization, even if neither the old nor new */
/* finalizer were NULL. */
/* Obj should be the nonNULL starting address of an */
/* object allocated by GC_malloc or friends. */
/* Note that any garbage collectable object referenced */
/* by cd will be considered accessible until the */
/* finalizer is invoked. */
So you define a callback:
typedef <any type at all you want passed to the callback
as data for its own use> MY_ENVIRONMENT;
void my_callback(GC_PTR void_obj, GC_PTR void_environment) {
MY_ENVIRONMENT *env = (MY_ENVIRONMENT)void_environment;
MY_OBJECT *obj = (MY_OBJECT*)void_obj;
// Do finalization here.
}
Create its environment (if any; otherwise just pass NULL):
MY_ENVIRONMENT *my_env = new MY_ENVIRONMENT;
// Initialize if necessary.
Then register it on a newly allocated object:
MY_
MY_ENVIRONMENT old_env;
GC_finalization_proc old_proc;
GC_register_finalizer(new_obj, my_callback, my_env, &old_env, &old_proc);
Now my_callback
will be called with your environment record when this particular object is collected.
As to your question 2, you're missing the point. Boehm GC replaces malloc/new and free and manages its own memory arena. It normally decides on its own when to do a collection. This is typically when most of the arena has been used up. Garbage collection identifies blocks that are free, hence eligible for reallocation. As the API notes clearly say, you can force a collection and force-free objects, but these are typically not necessary.