GNOME Bugzilla – Bug 336677
Documentation for g_object_ref_sink() is incorrect
Last modified: 2006-06-02 10:23:53 UTC
Documentation Section: Increase the reference count of object, and possibly remove the floating reference, if object has a floating reference. Correct version: It should say "If there is a floating reference, remove it, and if there is not, increase the reference count." Other information: The entire code in the g_object_ref_sink() function in gobject.c is as follows: { GObject *object = _object; gboolean was_floating; g_return_val_if_fail (G_IS_OBJECT (object), object); g_return_val_if_fail (object->ref_count >= 1, object); g_object_ref (object); was_floating = floating_flag_handler (object, -1); if (was_floating) g_object_unref (object); return object; } floating_flag_handler(object, -1), via object_floating_flag_handler(), removes the floating reference (if it was set) and if it was set returns true. Where it returns true, g_object_unref() is called giving rise to no net increment of the reference count. Unlike a GtkObject, a GObject still begins with a reference count of 1 (and g_object_ref_sink() will fail if the reference count is 0). That could also be made clearer in the documentation.
The language many not be the clearest, but I believe that it basically says the right thing. The important thing to keep in mind is that the floating reference is a regular reference, ie it contributes to the reference count. So, "removing the floating reference" means a) clear the floating flag and b) decreases the reference count.
Yes, it gets the floating reference right. However it says that if the floating reference is unset the reference count is still incremented. It isn't (it doesn't work like a GtkObject where you call g_object_ref() and then gtk_object_sink(), where the floating reference is, so to speak, converted into a strong reference). With g_object_ref_sink() the reference count is only increased if the floating reference is not set. A similar point arises earlier in the documentation for GObject, where it incorrectly says "The floating reference can be converted into an ordinary reference by calling g_object_ref_sink()". I think it important to make the point that it is different to the way GtkObjects work if people are not to get confused - I was until I looked at the source code and saw it was doing something different to what the documentation said. Unfortunately without an API break, you still have to look at the class heirarchy, or some other documentation (I hope there will be some), to see whether an particular object will has g_object_ref_sink() called on it (ie it is an old style GtkObject) or whether it doesn't (it is an old style GObject). In the latter case, to pass ownership to a container it will still be necessary to call g_object_unref() after putting it in the container in order not to break existing code - for example when placing a GtkTreeModel object in a GtkTreeView object.
g_object_ref_sink (foo) is exactly the same as g_object_ref (foo); gtk_object_sink (foo); I don't see what your problem is, honestly. Can you point me at any difference between the two ?
You are right that "g_object_ref(foo); gtk_object_sink(foo);" has the same effect as "g_object_ref_sink(foo)". However the effect of neither: g_object_ref(foo); gtk_object_sink(foo); nor g_object_ref_sink(foo); is the effect claimed for in the documentation for g_object_ref_sink(), namely: "Increase the reference count of object, and possibly remove the floating reference, if object has a floating reference." The real effect (of both sets of statements) is, as I said: "If there is a floating reference, remove it, and if there is not, increase the reference count." In other words, a GtkObject or new-style GObject begins life with a reference count of 1 and a floating reference, and after either of the sets of statements is called on it, it ends up with a reference count of 1 and no floating reference. Getting the description right for a new-style GObject is more important because a GTK+ container will not necessarily take ownership of it and, if it does not, the user has to understand that she needs to call g_object_unref() on it to dispose of it and/or pass ownership to an object which will not call g_object_ref_sink() on it. Finalising a GObject by calling g_object_unref() without having removed the floating reference does not generate a warning and is not regarded as mistake (it is necessary to retain compatibility with glib before version 2.10). Finalising a GtkObject by calling g_object_unref() without having removed the floating reference does generate a warning, since they are intended for insertion in GTK+ containers. I possibly misled you by saying that "Unlike a GtkObject, a GObject still begins with a reference count of 1". Objects of both types begin with a reference count of 1, although as I said if you call g_object_unref() on a GtkObject object without having removed the floating reference, you will get a warning. Although it would be inaccurate, it would not be a mistake to "picture" a GtkObject object as beginning life with a reference count of 0 and a floating reference, and after g_object_ref_sink() is called on it to picture it as ending up with a reference count of 1 and no floating reference. It would be a mistake to picture a new-style GObject this way if it is not intended for placing in a GTK+ container (example: placing a GtkTreeModel object in a GtkTreeView object). You are wrong that (in any formal sense): "that the floating reference is a regular reference, ie it contributes to the reference count. So, "removing the floating reference" means a) clear the floating flag and b) decreases the reference count." It does not contribute to the reference count (or if you want to picture it that way, a new
My last sentence was intended to say (I must have accidentally hit the magic key combination which sent the message): "It does not contribute to the reference count, because calling g_object_unref() on a GObject object will dispose of it without doing anything further, and must do so to maintain compatibility."
You seem to be missing the end of your comment, but as to "You are wrong that...", it's not up to *you* to define the terminology we use in the GLib docs. According to the maintainers of GLib, floating references are references and contribute to the refcount. It's fine to add explanatory text if necessary to clarify that ... the docs could say something along the line of: "If the object is floating, then this call "assumes ownership" of the floating reference, converting it to a normal reference by clearing the floating flag while leaving the reference count unchanged. If the object is not floating, then this call adds a new normal reference increasing the reference count by one." Maybe the docs already say something to that effect... I haven't checked. But your suggested change is completely and utterly wrong. You've misunderstood our terminology. Please readjust your understanding instead of campaigning to adjust our docs to your understanding.
It's a bug to call g_object_unref() on an object that has only a floating refcount. By doing that you are triggering undefined behavior ... maybe we don't warn currently, but we traditionally have done so for reference counts in GTK+.
It would a bug with a GtkObject. With a new-style GObject, if you are not to break API it is not a bug to call g_object_unref() on an object that has a floating reference count, since that is how GObjects have always worked (before version 2.10 they have never had a floating reference count). They have always begun with a reference count of 1, and are finalised by taking that count to 0. Would it help if g_object_ref_sink() took a GInitiallyUnowned argument rather than a GObject argument. I realise the two are typdef'ed to mean the same at present but presumably from what you say that is intended to change?
Actually I see the argument is a void* - the documentation says it is passed a GObject. Perhaps it ought to say it is passed a GInitiallyUnowned object.
On your pre-penultimate comment, I think all that has been said that can be said, and as you say the glib maintainers can call a floating reference an addition to the reference count if they want to do so. If they do so, in the case of a GObject on which g_object_ref_sink() has not been called - which as I have mentioned is not an error if you are to maintain API - you would have to regard g_object_unref as disposing of the floating reference and so finalising the object (even though it is not actually doing that). However that would still not make the comment about g_object_ref_sink() correct: "Increase the reference count of object, and possibly remove the floating reference, if object has a floating reference." It should say "Convert the floating reference to a strong reference, if the object has a floating reference, and if not increment the reference count."
Not worth debating further, but leaving open since it wouldn't hurt to add a few sentences to make it explicitly clear what the behavior is.
2006-04-03 Matthias Clasen <mclasen@redhat.com> * gobject/tmpl/objects.sgml: Add some verbiage to g_object_ref_sink_docs. (#336677)
This change has also corrected the statement in the documentation (gobject/tmpl/objects.sgml) that all GObjects are created with a floating reference. The documentation now states that GInitiallyUnowned objects are created with a floating reference. However this has only been applied to Glib-2.11. The point about g_object_ref_sink() is a bit optional, but I suggest the statements about GObjects being created with a floating reference is corrected in the Glib-2.10 documentation (this point cropped up on one of the mailing lists).