Re: Introducing "toggle references"



On Tue, 2005-04-26 at 02:01 +0200, Tim Janik wrote:
> On Mon, 25 Apr 2005, Owen Taylor wrote:
> 
> > (Why not g_object_toggle_ref() and g_object_toggle_unref()
> > to match g_object_weak_ref/unref()? they sound too much like they are
> > toggle the reference rather than add a "toggle reference.")
> 
> wouldn't it be better to call it toggle_link then, to make it less 
> similar to other *_ref() function names (which established the notion
> of a referencing action)?

Well, it actually increases the reference count of the referenced
object ... it's a strong reference with added notification properties.
So I want to keep the 'reference' name.

The 'toggle' part could probably be replaced. g_object_bistate_ref()
or something. But I'm reasonably happy with g_object_add_toggle_ref() 
as a name.

> > The big question is how to implement this efficiently. If we
> > implemented it like g_object_weak_ref(), then we would have to do a
> > qdata lookup each time the reference count of any object went from
> > 1 => 2 or from 2 => 1. Which is prohibitive.
> 
> just a note, i don't think the lookup is prohibitve if we know we're
> dealing with a toggle referenced object.

Yes, exactly, that's the point of introducing the flag stuck into
the gdatalist pointer.... to be able to cheaply tell if the object
is toggle referenced.

> > Other ideas:
> >
> > - We could squeeze two flag bits into object->qdata by
> >   using the 4-byte alignment. This would require modification
> >   of g_data_list_*() to mask out the bits.
> >
> >   Then we could use one of the flag bits to indicate whether
> >   there were any toggle references present.
> 
> [...]
> the remaining items you mentioned would increase the per-object size
> for struct GObject in general. at this point, there's not just Gtk+
> using GObject, so i'd like to strengthen the point that the effective
> memory size per GObject is not intended to grow any larger in *any*
> future version (that being the case since 2.0 actually).
> simply so that GObjects can be used as the "samll" objects they
> currently are (in arrays, pools etc.) with a guaranteed calculatable
> memory overhead.

I'm not a fan of increasing the size of GObject either. (There are
a number of small GObjects in Pango.) Though in terms of cheapness,
the time cost of creating a GObject is more of a concern to me than
the size...

> > Not really happy with any of these. The first approach though
> > ugly, would have the highest efficiency.
> >
> > In terms of the overall scheme, the main problem that I know
> > with it is that it can't handle the case of two language
> > bindings referring to the same object:
> >
> >        Language Runtime A                Language Runtime B
> >                            |           |
> >                            |           |
> >                    Proxy <--- GObject ---> Proxy
> >                           --->        <---
> >                            |           |
> >
> > Is still uncollectable.
> 
> so then, why not introduce add_/remove_ proxy_link (or proxy_ref) then,
> which notifies on the transition
> ref_count>n_proxy_links => ref_count=n_proxy_links ?
> 
> objects kept alive purely by proxy links shouldn't be interesting
> to language bindings, so they can drop their proxies with ref_count==1.

I had that thought, but it doesn't work out ... GObjects kept alive
only by proxy links *are* interesting. In a situation like:

        Language Runtime A                Language Runtime B
                            |           |
                            |           |
 Other object --> Proxy A <--- GObject ---> Proxy B
                           --->        <---

If we weaken the references from the GObject to the proxies, then
Proxy B will be collected prematurely.

> the idea being, that objects kept alive in one language environment,
> only by means of a variable or similar reference, will have to go through
> some gtk+ or otherwise auto-proxy-creation API point to again become
> visible in another language environment. 

OK, so the assumption you are making is that the proxy has no
interesting state attached to it. If that is actually the case
for one of the proxies then there is no reason for that language
runtime to use a toggle reference at all... the GObject can just
always weakly reference the proxy object.

But frequently there are reasons to keep the proxy around persistently:

 - The proxy is not a GtkWindow, but rather a language class deriving
   from GtkWindow with state stored in the proxy object. 
   Obviously this affects only one of the two objects in the above
   situation.

 - The user can attach data to the proxy object via language specific
   mechanisms. For example, in Python, you can just store data into
   a field of any object.

 - For garbage collection reasons, the language binding attaches
   closure data not to the GClosure, but rather to the proxy object.
   A leak in common case were the closure references the object and the
   object references the closure can be avoided this way. 
   (The python bindings do this. More bindings should do this.)

If any of these hold, then a toggle reference must be used.

> if there are solid reasons (non variable references from one language
> environment) to keep the object alive, there are non-proxy references
> on the object (container references, window list references, etc.)
> 
> regarding the implementation, you use your bit to indicate n_proxy_links>0
> and store the actual number of proxy references with the proxy notify
> array.
> 
> > It also can't handle cycles that go through multiple GObjects:
> >
> >                             |
> >                  Proxy A  <--- GObject A
> >                     |      --->  /|
> >                     |       |     |
> >                     |/      |     |
> >                  Proxy B  <... GObject B
> >                            --->
> >
> > But I don't know any way of handling these situations, so I don't
> > think they are worth worrying about. (The existence of an explicit
> > gtk_widget_destroy() is largely to handle the second situation.)
> 
> i don't think we shouldn't worry about a situation just because we
> don't yet know how to handle it (i.e. i don't follow your logic here).
> but i do agree that the second case with multi-object cycles is best
> handled by means of g_object_dispose(), it was introduced for that purpose.

Let me let me be less ambiguous in my phrasing. I believe there is
No Way to handle these situations other than using a common garbage
collector (*). So, lacking the capability to do the impossible, I'm
suggesting we handle what we can.

Regards,
							Owen

(*) OK, to be exactly precise here, let me admit that if a multiple
    object cycle can be traced using information known to the
    language binding then it is possible for certain customizable
    garbage collectors (Python and Ruby, for example) to collect the
    cycle. 

Attachment: signature.asc
Description: This is a digitally signed message part



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