The Problem =========== When a function calls raise_event, anything could happen, including the structure the function was working on being deleted further up/down the stack. It is also difficult to indicate to the caller of raise_event if one of the functions has deleted the structure it was working on, so it is very hard for the caller to TEST if the structure is still alive (magic tests are a sanity check, not an answer), since accessing free()d memory is illegal. Various solutions are listed below. Object Based Ref Counters. ========================== * All major structures in program are formed with object_* functions. * When an object is created, it is inserted into a hash table, and a handle to the entry is produced. * Handles are passed between functions rather than actual structures. * If a function needs to hold onto a structure beyond its call (or if the function is calling another function that *COULD* delete the object), then the function calls object_grab() and object_relase() when it is finished with the function Disadvantages ------------- * Increased overhead to grab objects from the hash (this shouldn't be too bad since the hash table should be very efficient) * Increased memory used with object prefixes to structures and the overhead of the hash table (which should be reasonably large to reduce collisions). * People will cry "THIS IS WHAT C++ IS FOR", but we will have those people shot when we achieve world domination. Advantages ---------- * Reduce the chance of refering to a deleted structure dramatically What it looks like ------------------ /* This structure will be hidden in obj.c */ struct object { unsigned long magic; /* Our sanity check */ unsigned short object_id; /* The ID of this object */ unsigned short used; /* Number of times its been grabbed (starts at 1 */ POOL p; /* Memory used to allocate this object */ }; /* This is an extract of obj.h */ typedef unsigned int HANDLE; typedef unsigned short obj_type_t; /* Error codes */ #define obj_err_ok 0 #define obj_err_invalid_name -1 #define obj_err_invalid_type -2 #define obj_err_invalid_handle -3 #define obj_err_invalid_ptr -4 #define obj_err_not_type -5 #define obj_err_invalid_obj -6 int object_register_type(obj_type_t *ans, const char *name); int object_new(void **ptr, obj_type_t type, POOL p, size_t size); HANDLE object_get_handle(void *obj); int object_get_obj(void **ptr, HANDLE h, obj_type_t expecting); /* Things we can do on an object */ void object_grab(void *obj); void object_release(void *obj); void object_free(void *obj); POOL object_get_pool(void *obj); obj_type_t object_get_type(void *obj); const char *object_get_type_str(void *obj); int object_get_grab_count(void *obj); Garbage Collection. ==================== Do all actual pool frees at idle time. Nothing (much) changes in the source code. However, it doesn't answer the problem of modules hanging on to a reference past idle time. Current theory is, if you hold on to a pointer to a structure past idle, you should be listening to the structures destroy event.