[Gtk-sharp-list] refcounting, GC, and glade.. (patch, need review)

Vladimir Vukicevic vladimir@pobox.com
14 Oct 2002 13:12:22 -0700


On Mon, 2002-10-14 at 09:01, Mike Kestner wrote:
> On Sun, 2002-10-13 at 18:04, Vladimir Vukicevic wrote:
> 
> > - We need to either:
> >   - Ref every object we get back, and create a separate C# wrapper every
> > time, even if the underlying Handle will be the same.  This seems the
> > easiest and least error-prone thing to do.
> 
> This will only ensure that the vast majority of GObject refs get leaked,
> because we own most of the refs that are returned by methods. What we
> need is a deterministic way to identify owned and unowned refs from the
> gtk API, which doesn't currently exist.  

Well.. I'm not convinced; Ref'ing things that we create is definitely
the wrong thing to do.. however, Ref'ing others I think is correct,
whether it's once and cache, or multiple times and create a new c#
wrapper each time, since, in theory, we shouldn't own any of those refs
unless we explicitly ref them.  And yeah, the gtk api sucks in this
respect.. I think they have pushed for some consistency on this issue in
the past though.

> >   - Ref only the first time we see a particular object pointer, and
> > store the C# object - return the same c# object for the same glib
> > object.  This would be doable, but tricky to get right -- by storing
> > those objects in the hashtable, they'll never get c# finalized, hence
> > never gobject unref'd.
> 
> No, it's not tricky to get right, and it's what we already do.  In the
> Raw property set code, we insert a hashtable entry to track existing
> wrappers.  In GetObject, we return the wrapper object for a given handle
> if it's in the hash, otherwise we wrap it, which eventually calls the
> GLib.Object(IntPtr) ctor, which sets Raw, which inserts it in the hash,
> yadayada.

Aye, I missed that.  However, it wasn't working -- for every call to
GetObject, I was getting a new C# wrapper.  The problem (I'm guessing)
here is that in the Raw property it's set as "Objects[value] = this",
but in GetObject it's accessed as "Objects[(int)handle]".. the HashCodes
may be different.

> This is easily accomplished via the Gtk.Object(IntPtr) ctor, if needed.
> However, I think the existing Dispose solution is fine. Perhaps the glue
> function should sink instead of unref, though, to avoid the harmless,
> but ugly, warning.

I looked at doing that; the only problem that I saw was that objects
that are created via the Object(IntPtr) ctor we have to assume that we
already own.  It's the objects that are created via things like
Gtk.Label:Label(string), which just does "Raw = gtk_label_new (str)". 
The only time we can Ref/Sink is after Raw is assigned to, but we only
need to Ref/Sink if it's a Gtk.Object derivative.  So perhaps we can
override Raw in Gtk.Object to do this.  This would mean, however, that
we can't use "Raw = blah" for the Object(IntPtr) case, since we don't
want to get reffed.

> > instead of just assigning to Raw as they do now.  All objects that are
> > returned by get_* or whatever functions should come unreffed -- in this
> > case we need to Ref() and create a C# wrapper.
> 
> Woah.  Who says that we don't own every ref returned by a get method? If
> that's true, then maybe that helps, but I doubt that is true.  The real
> issue is that the Gtk api is inconsistent in its ref ownership semantics
> and we need to overcome this with a solution that identifies unowned
> references so that we can ref only those. 

Owen claims that this is the case... the only exceptions, according to
him, are things that are legacy broken and are in deprecated code.

> Based on what I've read so far in this mail, I think the only likely
> result will be the leaking of refs, which we can accomplish by removing
> the Dispose functionality until we can solve the ref ownership
> identification issue.

I'll post a patch in a bit; unfortunately I'm about to get suckered into
'Real Work' for a while, so won't be able to clean it up for a little
while.

Thanks,
	- vlad

-- 
Vladimir Vukicevic <vladimir@pobox.com>