[gclist] Buffy finalizer slayer.

Charles Fiterman cef@geodesic.com
Fri, 11 Jun 1999 08:03:01 -0500


All problems with finalizers come from the fact they raise dead objects to
alter the bits of the living. Eliminate that and all the problems turn into
dust.

So instead of running a finalizer lets send out a death notice. I call
objects receiving a death notice watcher objects. One way of building a
watcher object is to include a weak pointer to the object to be shut down.
There are more efficient schemes but they require collector changes and
weak pointers are very safe and may have other uses. The watcher object
lives on a list of watcher objects and after each collection the user scans
the list for watcher objects that got a death notice in the form of a
zeroed weak pointer. Perhaps the collector could increment a count of weak
pointers zeroed which the user could decrement.

Those watcher objects can be run by the mutator and discarded doing the
work the finalizer would have done. If you have a file object that needs to
close when unreferenced its watcher needs a copy the file handle. In fact
the file object can be factored so the things needed by the watcher object
live there and the file object points to the watcher object. The user must
factor out the watcher object.

Lets open the medieval text on the evils of finalizers. It has plenty of
death and destruction but watcher objects seem to solve every problem.

Finalizers can save a pointer to their object creating a loose pointer or
raising it from the dead indefinitely. Watcher objects never have a pointer
to a dead object, if they did it wouldn't be dead.

Finalizers must run in an order determined by the collector with no
knowledge of mutator semantics. But this can involve never running the
finalizers at all if they point in a circle. Further that order may result
in keeping dead objects alive indefinitely as in a long list of finalizer
objects. Watcher objects all get death notices at the end of the collect
cycle and the mutator determines their order. If the mutator can't the
collector doesn't have a hope.

Finalizers may allocate storage and trigger a collect from within the
collector. Watcher objects are run from within the mutator and if they
trigger a collect the mutator gets to ask mutator type questions like "Do I
resort the watcher objects?"

Finalizers left unrun at end of job can only be discarded. Any watcher
objects still unnotified at end of job are still on a list and the mutator
can decide what to do with them. This requires semantic information the
collector doesn't have and can't get.

Finalizer objects may throw exceptions from within the collector which has
no notion of what to do with them. Watcher objects throw exceptions from
within the mutator which knows exactly what to do with them if anyone does.

Finalizer objects are run in the thread that ran the collection which is
likely to be chosen at random. Watcher objects are run by the mutator in
the manner chosen by the mutator. The mutator can point some other object
at an active watcher to run at a really good time.

Finalizer objects require extra collector overhead in a world where we are
judged by latency. Watcher objects run at the convenience of the mutator.

A garbage collector says "I'll give you the illusion of infinite storage by
freeing objects that can never influence the order of execution again."
Finalization says "Once an object can never influence the order of
execution again I'll run a function that knows its address so it can
influence the order of execution and maybe live for thousands of years or
end of job which ever comes first." This cannot be a good idea. Lets drive
a wooden stake through its heart.




 



Charles Fiterman		  Geodesic Systems
414 North Orleans Suite 410	  Phone 312 832 2015
Chicago IL 60610-4418           FAX   312 832 1230
				  http://www.geodesic.com

...computers in the future may have only 1,000 vacuum tubes 
and weigh only 1/2 tons.  --  Popular Mechanics, March 1949