[prev in list] [next in list] [prev in thread] [next in thread]
List: gtk-devel
Subject: Re: Sinkability considered harmful
From: "Gustavo J. A. M. Carneiro" <gjc () inescporto ! pt>
Date: 2006-01-03 23:43:00
Message-ID: 1136331780.24121.6.camel () localhost ! localdomain
[Download RAW message or body]
[Attachment #2 (multipart/signed)]
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
["signature.asc" (application/pgp-signature)]
_______________________________________________
gtk-devel-list mailing list
gtk-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-devel-list
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic