Re: GObject reference counting / lack of "sink" issue



On Thu, 29 Sep 2005, Andrew Paprocki wrote:

Tim,

I am struggling with the reasoning behind providing "sink" functionality in GTK,
but not in GObject, and I am wondering if you could shed some light on the
subject. We use GLib/GObject extensively internally at our firm and there are
hundreds of thousands of lines of code that are written in the GObject API
style. It is in my interest to stay as close to the upstream GObject
implementation as possible, which is why I am writing.

I am in the middle of crafting a new API in which callers will need to create
custom GObjects and pass them into a container of sorts (also a GObject) at
which point the container needs to take ownership of passed objects. If we do
not want to require the user to g_object_unref() the object, how can the object
system be used appropriately to handle this situation so the container takes
ownership of the object via an "add()" API and ensures there are no leaked
objects when the "remove()" API is called.

The GtkObject "sink" functionality seems exactly what is needed, but I can't
understand why this functionality is restricted to GTK. I have come across other
implementations (GStreamer comes to mind) where they simply re-invented the
wheel. Short of re-creating another custom ref/sink wrapper for GObject, is
there any other option or hope of moving this functionality into GObject itself?


i was originally going to write the usual reply about GObject extensions
along the lines of:
  GObject is a three field structure not meant to grow (keeping it the small
  size it currently has is actually a significant design goal of its API and
  implementation). it doesn't have the GtkObject flags field and as such can't
  hold an extra floating flag.

but come to think of it, this isn't entirely true (anymore).
looking at gtkobject.c, the floating flag is used very rarely:
- upon _init, since it has initially to be set
- upon _sink, to figure whether an _unref is pending
- upon finalize for some sanity checking
none of these uses is performance critical in any reasonable scenario,
so the floating flag might just be stored away via g_object_set_data().
in fact, this is exactly how GParamSpec implements its floating/sink
behavior.
but more than that; Owen Taylor recently shoveled space for two extra flags
per GObject by making use of pointer alignments. one such flag is used for
toggle references, the other is still free and provides a good future
floating flag candidate.

you are right, GObject is widely used these days out of GtkObject contexts,
and anywhere in C land (where memory book keeping or reference house keeping
can't be automized) when objects are created and ownership is passed on,
a floating flag is strongly desired (and forces you to derive and reimplement
if you're consequent enough ;)

so for a change, i'd like to suggest introducing extra API (and do some slight
deprecations) for this and apprechiate people's comments on it:

/* ref() and clear floating flag (#1) */
GObject*    g_object_ref_sink       (GObject *object);

/* figure whether floating flag is set */
gboolean    g_object_is_floating    (GObject *object);

/* intended for object implementations only, sets the floating flag */
void        g_object_force_floating (GObject *object);

/* added to keep the API consistent (#1) */
GParamSpec* g_param_spec_ref_sink   (GParamSpec    *pspec);

/* deprecate even more GtkObject API */
+#ifndef GTK_DISABLE_DEPRECATED
 typedef enum {
   GTK_FLOATING,
 } GtkObjectFlags;
 #define GTK_OBJECT_FLOATING(obj)          ((GTK_OBJECT_FLAGS (obj) & GTK_FLOATING) != 0)
+#endif

and introduce some behavioral changes:
- call g_object_force_floating() on newly constructed objects
- auto-clear or ignore the floating flag upon finalize; so
  floating objects do not *have* to be sunken, which keeps compatibility
  for existing GObject uses. this will leave the stronger checks
  in place that currently apply to GtkObjects
- port gtkobject.c to use the GObject floating flag instead of
  GTK_OBJECT_FLOATING() and GTK_FLOATING. this does break binary
  compatibility with existing code that makes use of GTK_OBJECT_FLOATING()
  though. but i do have one or two backup plans in mind if this really
  is considered a problem. so people who are concerned about this
  should speak up now.


#1) in allmost all cases where the _sink() API is used, it's used in
    combination with _ref() similar to:
      g_object_ref (object);
      g_object_sink (object);
    so this may as well be a single function call, especially since
    this function call may then conveniently return the object
    handle the way _ref() already does it. in the pretty rare
    scenarios where the automatically added reference count is not
    usefull (e.g. when emulating gtk_object_sink()), a combination of
    _ref_sink() and _unref() can be used instead.

Thanks,

Andrew Paprocki

---
ciaoTJ



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