Completely agree. Interesting read too. I'd just like to add one more thing. g_object_new *should* always return a new reference, to be owned by the caller. It usually does, except for g_object_new(GTK_TYPE_WINDOW, NULL), in which case the caller does not own the object ref. I don't quite understand how this happened. It should not be due to backward compatibility because this is a new API (in glib 2.0). So I would add "g_object_new returning borrowed references considered harmful", to avoid more problems like this in the future. Cheers. On Tue, 2006-01-03 at 17:07 -0600, Federico Mena Quintero wrote: > Sinkability considered harmful > ------------------------------ > > Why do we have sinkable objects, i.e. gtk_object_sink()? > > It is a historical artifact. Early versions of GTK+ did not have a > consistent or even correct policy for memory management. > > In 1997, Marius Vollmer (a Guile hacker with experience in garbage > collection and automatic memory management) revised most of the code > in GTK+ to use reference counting consistently: > > http://mail.gnome.org/archives/gtk-list/1997-November/msg00229.html > > Owen merged some of these changes (gtk+/ChangeLog.pre-1.0): > > Wed Dec 17 21:09:12 1997 Owen Taylor <owt1 cornell edu> > 1997-10-13 Marius Vollmer <mvo zagadka ping de> > > [...] > > Revamped reference counting, see the file REFCOUNTING. > > Early in 1998, Tim Janik merged most of the changes into GTK+ > (gtk+/ChangeLog.pre-1.0): > > Fri Jan 30 23:55:03 1998 Tim Janik <timj gimp org> > > * Incorporation of Marius Vollmer's reference counting revolution, > plus various fixups and additions from myself. > > [...] > > * gtk/gtkobject.c: new functions gtk_object_finalize, > gtk_object_notify_weaks, gtk_object_debug, gtk_object_sink, > gtk_object_weakref, gtk_object_weakunref. implementation of the new > reference counting scheme for gtkobjects (consult gtk+/REFCOUNTING). > > See the last part of this mail: > http://mail.gnome.org/archives/gtk-list/1997-November/msg00245.html > > Quote: > > The complicated rules about GtkWidgets and their `floating' > flag are there to avoid breaking *all* existing code. > > So, what happened? > > We started using reference counting in a consistent fashion. Even if > not all structures and objects derived from GtkObject, they provided > their own foo_ref() and foo_unref() functions. > > Client code seldom used "internal" objects like GdkFont, so it didn't > need to ref/unref those objects. For example, in an expose handler > you could simply access widget->style->font, as you would not be > storing that font for usage elsewhere. > > > Widgets are special > ------------------- > > GTK+ always had this usage convention for widgets: > > GtkWidget *the_widget; > > the_widget = gtk_some_widget_new (); > gtk_container_add (some_container, the_widget); > /* I no longer own the_widget; some_container owns the base reference */ > > The convention is that once you insert a widget in a container, you > no longer own a reference to the widget. > > Contrast this with a "normal" reference-counted API, where you do this: > > Obj *obj; > > obj = some_object_new (); > /* reference count of obj is now 1 */ > > container_add (container, obj); > /* reference count of obj is now 2 or more */ > > some_object_unref (obj); > /* This code no longer owns a reference to obj, but the > * container does. > */ > > ... but old code that used GTK+ did *NOT* require you to unref() the > object after adding it to a container, and we did not want to break > that code. WE HAVE LIVED WITH THAT CONVENTION EVER SINCE. > > The "floating" flag was introduced in GtkObject to: > > 1. keep this convention > > 2. make things easier for language bindings. > > So, to summarize: the floating flag was added to avoid changing GTK+ > client code, and to make things friendly to language bindings which > perform their own memory management. You do *not* need a floating > flag in a normal reference-counted API. > > All GtkObjects start with the floating flag turned on. Inside the > code for containers, you can see this: > > gtk_some_container_add (GtkSomeContainer *container, GtkWidget *child) > { > gtk_object_ref (child); > gtk_object_sink (child); > add_child (container->children, child); > } > > With this scheme: > > 1. Right after creation, the initial reference of an object is said to > be floating. > > 2. When you put the object in a container, the container first refs > the object, then sinks it. > > void > gtk_object_sink (GtkObject *object) > { > if (GTK_OBJECT_FLOATING (object)) > { > GTK_OBJECT_UNSET_FLAGS (object, GTK_FLOATING); > gtk_object_unref (object); > } > } > > From the viewpoint of the container, this means: if no one had > claimed ownership to the initial reference of the object, I'll > claim it myself. Otherwise, I'll simply acquire a new reference to > the object. > > 3. The calling code no longer owns the initial reference. > > > Widgets are inconsistent > ------------------------ > > If you had an API where everything was "purely" reference-counted, you > would always acquire a reference when you needed one, and release it > when you no longer need it. This makes using the API reasonably > easy. You have to type a bit more to make the call to unref(), but at > least your code is consistent. > > When certain objects have a floating flag and a sink() method, you as > a programmer need to keep in mind a special case. Users of GTK+ have > kept this in mind for GtkWidget and its descendants since 1998. > > Many APIs have abused float/sink "to make things easier for the > programmer", so that he doesn't have to unref() an object after > passing it to a container-like object which acquires a reference. > Recent culprits include gtk_file_filter_new() and > gtk_file_chooser_add_filter(), even though filters are not widgets! > > > Good practices for new APIs > --------------------------- > > Just make them purely reference-counted as derived from GObject. If > your API has container-like objects which hold other objects, you'll > need to unref() the children by hand after inserting them in the > container. > > Using floating references and a sink() method just makes life harder > for everyone: > > 1. Users have to keep in mind that those objects are special. > > 2. Language bindings have to go through contortions to get the > references right. > > > Summary > ------- > > Let's not have a floating flag in GObject, as it promotes bad API > practices. > > Let's keep GtkObject and GtkWidget as they are, as a historical > artifact, and just let language bindings deal with them as they do > now. > > APIs which want to reinvent float/sink do so at their own peril. > > Federico > > > _______________________________________________ > gtk-devel-list mailing list > gtk-devel-list gnome org > http://mail.gnome.org/mailman/listinfo/gtk-devel-list -- Gustavo J. A. M. Carneiro <gjc inescporto pt> <gustavo users sourceforge net> The universe is always one step beyond logic
Attachment:
signature.asc
Description: This is a digitally signed message part