Re: GObject and Gtk+ Finalization



Maciej Stachowiak <mjs eazel com> writes:
> Havoc Pennington <hp redhat com> writes:
> 
> > Maciej Stachowiak <mjs eazel com> writes: 
> > > What would be the correct way to do cleanup of resources used by the
> > > object that is compatible with both Gtk 1.2 and Gtk 2.0?
> > > 
> > 
> > Do all cleanup in the finalize method.
> > 
> 
> Well whoops, pretty much all of Nautilus is doing it wrong.
>

Well you aren't doing it wrong for 1.2, just wrong if you want to
convert things to GObject, which isn't actually _necessary_ just handy
to strip the GTK library dependency when/if you want to do that.
Typically this isn't even possible for released APIs because of the
floating refcount issue, all user code suddenly leaks memory if you
convert to GObject... but GtkObject stuff that's not yet released can
be hacked to ref/sink in the constructor and thus avoid changing
semantics on GObject conversion.

destroy/finalize have always had separate purposes, in 1.2 roughly
destroy was supposed to break references held to other refcounted
objects while finalize was supposed to actually free everything else,
and it was supposed to be safe to invoke any method of an object on a
destroyed object (though for much of GTK+ this wasn't true). So much
code does too much freeing in the destroy method, even by 1.2
semantics.

In 2.0 destroy on a widget is allowed to be called multiple times, so
this in effect means only that "safe to invoke any method" is extended
to also include the destroy method. The easiest way to implement such
safety is to demand-create resources, e.g. always get your vadjustment
by calling get_vadjustment() which creates the adjustment if it's
NULL.

> Another question: what's the right way to be notified of a non-widget
> object's destruction that's both Gtk 1.2 and 2.0 compatible? This is
> pretty essential for proper factory lifecycle management when using
> Bonobo.
> 

The simplest way is to set object data with a destroy notifier. (Note
that "destroy notifier" here means it's called on finalize, as it is
in GtkObject now. Be careful because unlike with a callback connected
to the "destroy" method, with a finalize notifier it's pretty trivial
to create a cyclic refcount. "destroy" is more or less a solution to
the cyclic refcount problem, which GObject does not provide for you
since it's perhaps not a generic or typically appropriate solution for
non-GUI objects. Well, "destroy" is also in part a historical artifact
of the fact that widgets weren't always refcounted.)

Havoc






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]