Finalization

David Shaffer cdshaffer at acm.org
Sat Mar 25 04:53:31 UTC 2006


Andreas Raab wrote:

> What you've described is not a bad idea in general (and it's probably
> what VW does) but there are things that I don't like about it. For
> example, part of why the finalization process takes so much time is
> that there are so many weak references lost that we don't care about -
> the whole idea that just because you use a weak array you need to know
> when its contents goes away is just bogus. Secondly, once you start
> relying on "accurate" finalization information you should really make
> sure it's accurate (e.g., one signal/entry per finalized object). And
> once you do that you need to deal with the ugly corner cases of an
> overflow of the finalization queue (and the effect that you probably
> can't allocate any larger one because the GC you're currently in was
> triggered by a low space condition to begin with ;-) Nasty, nasty issues.

Agreed.  Presumably it would be one queue per user-specified group of
weak objects...similar to the Java implementation in the sense that
"weak containers" can specify a queue if they like, otherwise a
system-wide one is used.  Anyway I think you're idea is better...

>
> Having said that, let me propose a mechanism that (I think) is
> fundamentally different and fundamentally simpler. Namely, to make the
> requirement that you only get notifications for the finalization of
> objects that you explicitly register for by creating a "finalizer"
> object, e.g., an observer which is allocated before it's ever needed.
> This simple change avoids both the problem of GC needing to allocate
> memory when there is none as well as sending notifications about
> finalizations that nobody cares about, which are both very desirable
> properties. When the object becomes eligible for garbage collection,
> the finalizer is then put into a list of objects that have indeed been
> finalized and the finalization process simply pulls them out of the
> queue and sends #finalize to them.
>
> In its simplest form, this could mean a finalizer is a structure with
> (besides the prev and next links for putting it into a structore) two
> slots a "weak" slot for the object being guarded and a "strong" slot
> for the object performing the finalization (its #finalizer). When the
> garbage collector runs across a Finalizer and notices its observed
> value is being collected, it can simply put the finalizer into the
> finalization list and is done. (btw, this scheme is *vastly* easier to
> implement than your proposed scheme since everything is pre-allocated
> and you only move the object from one list to another).

This sounds great.  Some implementation hints?  I assume I'd need to
make the weak entry recognizable by #nonWeakFieldsOf: but I don't
understand the class format voodoo in that method.   Also it seems that
the weak slots have to come after the non-weak slots...just a detail but
is this correct?

>
> But while we're at it, we could also shoot a little bit further and
> get away from post-mortem finalization (which I find a highly
> overrated concept in practice). The only thing we'd change in the
> above is that the garbage collector would now also transfer the object
> from the "weak" into the "strong" slot[*1]. This makes the finalizer
> the sole last reference to the object. If the finalizer drops it, it's
> gone. If the finalizer decides to store it, it will survive. Lots of
> interesting possibilities and much cleaner since you gain access to
> the full context of the object and its state.
>
> [*1] The easiest way to do this would be to simply clone the object
> but unfortunately this also has the unbounded memory problem so
> something a bit more clever might be required. Basically we really
> want *all* references to the object except from the finalizer to be
> cleaned up.

Yes this would be nicer than the "executors" which don't really have
much to go on.  Why would we copy?  Why not some other color mark for
object reachable through the weak reference (but not through others, of
course)?  Then the sweep phase could identify those that are only weakly
reachable and perform your switcheroo.

>
> Note that weak arrays or other weak classes wouldn't be affected at
> all by this since only Finalizers get the notifications - all other
> weak classes would simply drop the references when they get collected
> and never get notified about anything.

Yes I guess that WeakRegistry would be the only class significantly
impacted by this.  I see a few other senders of addWeakDependent:
arround but it looks like the effort to move those to this scheme would
be relatively minimal.

David




More information about the Squeak-dev mailing list