The memory-management API for GObjects is a bit complicated but the idea behind it is pretty simple: the goal is to provide a flexible model based on reference counting which can be integrated in applications which use or require different memory management models (such as garbage collection, aso...). The methods which are used to manipulate this reference count are described below.
/*
Refcounting
*/
gpointer g_object_ref (gpointer object);
void g_object_unref (gpointer object);
/*
* Weak References
*/
typedef void (*GWeakNotify) (gpointer data,
GObject *where_the_object_was);
void g_object_weak_ref (GObject *object,
GWeakNotify notify,
gpointer data);
void g_object_weak_unref (GObject *object,
GWeakNotify notify,
gpointer data);
void g_object_add_weak_pointer (GObject *object,
gpointer *weak_pointer_location);
void g_object_remove_weak_pointer (GObject *object,
gpointer *weak_pointer_location);
/*
* Cycle handling
*/
void g_object_run_dispose (GObject *object);
The functions
Finally, after finalize is invoked,
The table below summarizes the destruction process of a GObject: Table 5.
Weak References are used to monitor object finalization:
Weak References are also used to implement Note: the following section was inspired by James Henstridge. I guess this means that all praise and all curses will be directly forwarded to him. GObject's memory management model was designed to be easily integrated in existing code using garbage collection. This is why the destruction process is split in two phases: the first phase, executed in the dispose handler is supposed to release all references to other member objects. The second phase, executed by the finalize handler is supposed to complete the object's destruction process. Object methods should be able to run without program error (that is, without segfault :) in-between the two phases.
This two-step destruction process is very useful to break reference counting cycles.
While the detection of the cycles is up to the external code, once the cycles have been
detected, the external code can invoke
Attentive readers might now have understood one of the rules about the dispose handler
we stated a bit sooner: the dispose handler can be invoked multiple times. Let's say we
have a reference count cycle: object A references B which itself references object A.
Let's say we have detected the cycle and we want to destroy the two objects. One way to
do this would be to invoke If object A releases all its references to all objects, this means it releases its reference to object B. If object B was not owned by anyone else, this is its last reference count which means this last unref runs B's dispose handler which, in turn, releases B's reference on object A. If this is A's last reference count, this last unref runs A's dispose handler which is running for the second time before A's finalize handler is invoked ! The above example, which might seem a bit contrived can really happen if your GObject's are being handled by language bindings. I would thus suggest the rules stated above for object destruction are closely followed. Otherwise, Bad Bad Things will happen. |