Re: GTK_FLOATING broken in 2.9?



Hi,

The way I've always thought about the floating flag is that when you
create a new object, *you* don't own a reference. Instead, there's a
floating reference with no owner, and anyone is allowed to remove that
floating reference since it's "community property" - the "if floating
exists remove it" operation is sink().

This seems fundamentally incompatible with today's GObject, where if you
create a new object you *do* own a reference.

There's another possible definition of the floating reference, which is
that its owner is defined per-type. So for example, for GtkWidget the
owner of the floating reference is defined to be the GtkContainer
system. In this world, arguably the floating reference can be ignored by
everyone except the defined floating reference owner.

With this we could say something like "all GObject types that exist
already in a public ABI are defined to have the floating ref owned by
the object creator, except GtkObject subclasses where the floating owner
was already defined. New GObject types may define a floating ref owner
other than the object creator." Then arguably it's compatible to add
floating to GObject.

I don't think this "floating owner is defined per-type" way of thinking
is accurate, though. In reality anyone can sink, and there are
legitimate reasons for anyone to sink: never adding the widget to the
container, language bindings, etc. That's why I prefer the definition
that the floating reference is, well, floating. Anyone can sink it. This
seems to be more not less likely for GObject, vs. GtkWidget. 

Allowing plain unref() to remove the floating reference shows the
conceptual bug. You can't call unref() on an object with only a floating
reference, because *you don't own a reference count*. And you have no
way of knowing the floating reference still exists, except in simple
contrived examples. So unref() on an object with floating=true
refcount=1 IMHO has to be a bug, or the whole design is broken.

If we make that a bug that warns, we'd have this GObject change printing
warnings all over the place, and I think for good reason.

The previous warning in gtk_object_finalize makes the same claim about
what FLOATING means that I'm making here:

  if (GTK_OBJECT_FLOATING (object))
    {
      g_warning ("A floating object was finalized. This means that someone\n"
                 "called g_object_unref() on an object that had only a floating\n"
                 "reference; the initial floating reference is not owned by anyone\n"
                 "and must be removed with gtk_object_sink() after a normal\n"
                 "reference is obtained with g_object_ref().");
    }

If that's true, I don't think adding floating to GObject can possibly be
compatible.

In practice of course, if nobody ever calls sink() on a type that exists
today, nothing will break. However, that situation has no chance of
lasting; people will start to sink object types that exist today, and
that will always be an incompatible change if done in a library.

It seems to me there's a very simple and standard solution for adding a
new method and feature to an object, which is a subclass. Why not
GFloatingObject? With GFloatingObject people can do:

  if (G_IS_FLOATING_OBJECT(obj))
      ref_sink(obj);
  else
      ref(obj);

instead of:

  if (object type was in a public ABI prior to December 2006) 
     ref_sink(obj);
  else
     ref(obj);

Full proposal:

 - GObject has a floating flag, but it's false by default and 
   object creator owns a hard reference
 - there's a method float() to set the floating flag to true; 
   you must own a reference to call it, and the ref you own 
   becomes community property / floating
 - GFloatingObject calls float() at construct time to float the 
   initial reference; creator of GFloatingObject owns no ref
 - GtkObject also calls float() at construct time, but does not
   derive from GFloatingObject, just uses the same facilities
   to implement floating
 - it's an error to unref with the floating flag set
   and refcount = 1
 - (optionally) in the gtk+ stack, GFloatingObject is never used, 
   because it would be too confusing to mix these in with the old 
   APIs
 - (definitely) something that's a GObject today can't be changed to
   GFloatingObject or to call float(), this is incompatible

Havoc





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