This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Marking smobs for GC


Russ McManus <russell.mcmanus@gs.com> writes:

> Marius Vollmer <mvo@zagadka.ping.de> writes:
> 
> > Let me drone on a little bit.
> 
> I read your discussion with great interest, because I have given this
> problem a bit of thought myself in the context of some of the programs
> I've written that use guile, and that also have to play nice with
> external systems that do their own resource management.

Yes, one of my motivations was to solve this problem in general, even
if in the specific situation involving Gtk+ there might be cheaper
copouts.  I was reasonably happy once I discovered a theoretically
pleasing and sound method so I just implemented that and stopped
thinking too hard about possible trade-offs between efficiency and
elegance.  Should the counting and tracing prove to have an
unacceptable overhead, I might have to revisit this issue, but for now
I'm going for perfectionism.

> What is interesting to me about your strategy is that it attempts to
> share the responsibility for the lifetime of an object between the
> Scheme world and the outside world.  Generally I have given up and
> given ultimate control of an object's lifetime to one of the two
> worlds.  From your description, it sounds like the in-between strategy
> can work, with a signficant amount of additional complexity.

I'm not sure if the additional complexity is really significant.  I
have not profiled the thing, and now that I think about it, there
might be one combinatorial explosion in the code that could be
avoided, but even when you have a CList with 10000 entries (widgets)
the GC pauses are barely noticable.

There is a certain additional `mental' complexity in the algorithm,
but that shouldn't matter much.

> GTK widgets are an interesting application for this idea, because
> AFAIK, the object's lifetimes really are determined outside of the
> Scheme world's domain, because the user can tell the X server to nuke
> a particular window at any time.

A Gtk widget leads a complicated life, especially when getting
retired.  When the users tells a widget to go away, it is "destroyed".
This destruction is a normal event, like a button click, as far as
Scheme is concerned.  The widget looses its XWindow and most of its
useful functionality, but it is still there.  It still has state and
can be queried about it, for example.  The reference count of the
widget controls only the `internal' resources, like the memory for the
struct of the widget, the GtkStyle that hangs off of it, and so on.
When the last reference count is removed, the widget is `finalized',
which amounts to really freeing the underlying memory.  [There is now
an additional action called `shutdown' which I don't understand.]

So, even when a widget has been destroyed, the user (regardless
whether C or Scheme) can still deal with that widget just fine.  He
can still query the state of the thing.  In fact, the distinction
between destruction and finalization is more important to C than to
Scheme or any other language binding that has proxies.  C needs to
have a way to keep a widget struct from disappearing so that it can
store pointers to it and be sure that they don't go away.  Originally,
destruction and finalization were combined in Gtk+ and thus you could
either keep a widget struct around, or allow the XWindow to go away.
Not a nice situation.

> What does it mean then to have a live Scheme object representing a
> GTK widget, if that widget's window is gone?  At that point, a
> nonzero reference count still doesn't leave you with a useful
> object.

You have still a valid widget, but one that is in a `destroyed' state
(there is even a flag you can test).  I'm not sure if the destroyed
state is well defined, tho, because I'm not sure if you can haul a
widget back into life by `realizing' it again or some such and if Gtk+
can sanely deal with attempts to do so.

> What about the situation when the lifetime of the object is decided
> outside of Scheme?  Then it's possible, or even likely that captured
> references to these object will become stale at some point.  The
> approach I have adopted is stolen from Emacs's buffer handling.

The Gtk+ approach is about the same, using the `destroyed' state of a
widget.

I found it to be the cleanest approach when proxy and widget live and
die together so that they can really be treated as an atomic unit.

For example, you can put the proxy into a weak hash table and it will
stay there as long as the widget is in use by the GUI even if there
are no other references to it from Scheme.  I think it is important
that this works, but when the link from the widget to the proxy is
weak, your proxy can be collected prematurly.

On the other hand, a dying proxy should take the widget with it, when
there are no other references to the widget.  Consider the case where
the user creates a widget and then does absolutely nothing with it.
The proxy gets collected and the widget needs to go, too, but when the
link from proxy to the widget is weak, it can't do that because it
wouldn't be enough to keep the widget alive in the first place.

So, both links need to be `strong', which would be no problem if Gtk+
would use a tracing collector as well (and Guile's and Gtk's collector
could be made to cooperate), but it only has ref counting, so we need
to look out for cycles, which leads to the complicated machinery
described in my previous post.

> So if I were writing a GTK interface, I would have just used
> 'widget-live?' or some such.  Maybe this is a loser for some reasons
> that I'm missing, but the strategy has worked for me in other
> contexts.

I started out this way, too.  The predicate was called
`gtk-destroyed?', I think.  I'm not really sure if the argumentation
for requiring both links to be strong is really `forcing', but for now
I have pretty much convinced myself that anything else has worse
problems.

- Marius

--
GNOME: First Church of Appliantology