[gclist] Finalizer flame wars.

Charles Fiterman cef@geode.geodesic.com
Thu, 9 May 1996 13:18:01 -0500


> > Collectors need to be efficient and transparent.
> 
> Efficient, yes!
> Transparent, not necessarily!
> 
> > Adding finalizers hurts their efficiency and transparency.
> 
> That's probably where we disagree. A tracing collector is an incredible source
> of information thanks to the graph traversal it performs. I think it can
> be worth adding hooks to the GC to allow programs to take advantage of this
> information.

Please give examples. I'm fascenated. The one I want is "Why are you keeping
this object alive?"

>
> Similarly, I think it can be worth allowing programs to specify a "copying"
> operator for some objects that can be used by a stop&copy-style collector
> instead of a "bit-copy". The idea is that, since the copying has to take place,
> it can be a good occasion to do some semantically non-effecting cleanup (for
> instance).

I agree. The hack I love is user defined mark methods. For example a symbol table
in a compiler could keep things alive simply because they were put on the table
in the first pass. In the second pass it could mark nothing. Table entries kept
alive from outside the table structure would live, the others would be deleted
from the table by their finalizers. This is a elegant clear encapsulation of 
a complex problem.

The problem with all this stuff is that if buggy the problem appears far from the
source. For example suppose a user defined mark method failed to mark an object
that was actually in use. You now have a wild pointer bug. The problem with your
semantically non-effecting cleanup is that a bug could make it semantically effecting.

So as a language designer I opt for transparent. The user should be unaware of
the collector. I am considering the option of saying the language protects the
user from himself unless he says I know what I'm doing leave me alone. For example
assignments are rigidly type checked unless the user says something like "shove".
But the execptions where the user tells the language to bug off should be very
rare. In C++ type casts occur almost every line.
 
> > Giving them over to collectors destroys both. In encapsulation terms they
> > are a match made in hell. 
> 
> Obviously, you don't have anything against finalizers, you just want something
> else. Maybe you could extend finalizers with options like "be prompt" that
> tells the compiler that this finalizer should be called as soon as the object
> is not reachable (rather than "as soon as you can"). This would instruct the
> compiler to try to stack-allocate the object or to ref-count it or
> I don't know what.

The trick I'm working on is a finalizer-destructor graph. This handles calling
finalizers and destructors. The former preserves invariants the latter does not.
It uses reference counting and reports destructor cycles as errors. It keeps
objects on the graph alive by virtue of maintaining pointers to them. It lives
on top of the object system far from the collector. When it is done with objects
they disapear from its graph and if nothing else needs them the garbage collector
deletes the object. That is it uses the collector implicitly like any other 
directed graph.