GObject Reference Manual |
---|
Again, it is often difficult to figure out which mechanism to use to
hook into the object's destruction process: when the last
g_object_unref
function call is made, a lot of things happen as described in
Table 5, “g_object_unref”.
The destruction process of your object might be split in two different phases: dispose and the finalize. This split is necessary to handle potential cycles due to the nature of the reference counting mechanism used by GObject, as well as dealing with temporary vivification of instances in case of signal emission during the destruction sequence.
struct _MamanBarPrivate { GObject *an_object; gchar *a_string; }; G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT) static void maman_bar_dispose (GObject *gobject) { MamanBar *self = MAMAN_BAR (gobject); /* In dispose(), you are supposed to free all types referenced from this * object which might themselves hold a reference to self. Generally, * the most simple solution is to unref all members on which you own a * reference. */ /* dispose() might be called multiple times, so we must guard against * calling g_object_unref() on an invalid GObject by setting the member * NULL; g_clear_object() does this for us, atomically. */ g_clear_object (&self->priv->an_object); /* Always chain up to the parent class; there is no need to check if * the parent class implements the dispose() virtual function: it is * always guaranteed to do so */ G_OBJECT_CLASS (maman_bar_parent_class)->dispose (gobject); } static void maman_bar_finalize (GObject *gobject) { MamanBar *self = MAMAN_BAR (gobject); g_free (self->priv->a_string); /* Always chain up to the parent class; as with dispose(), finalize() * is guaranteed to exist on the parent's class virtual function table */ G_OBJECT_CLASS (maman_bar_parent_class)->finalize (gobject); } static void maman_bar_class_init (MamanBarClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->dispose = maman_bar_dispose; gobject_class->finalize = maman_bar_finalize; } static void maman_bar_init (MamanBar *self); { self->priv = maman_bar_get_instance_private (self); self->priv->an_object = g_object_new (MAMAN_TYPE_BAZ, NULL); self->priv->a_string = g_strdup ("Maman"); }
It is possible that object methods might be invoked after dispose is run and before finalize runs. GObject does not consider this to be a program error: you must gracefully detect this and neither crash nor warn the user, by having a disposed instance revert to an inhert state.