[gclist] Re: Mark don't sweep

Robert A Duff bobduff@world.std.com
Fri, 10 May 1996 09:42:06 -0400


Amit J Patel <amitp@Theory.Stanford.EDU> says:

> I have a slightly different view of the finalizers:  I view them as
> functions that must be run before the program ends, but the time at
> which they are executed is not determined.  The only guarantee is that
> the function is executed between the point that the object becomes
> garbage and the end of the program.

This makes sense, and I don't see how you can do better.  If the
non-determinism is unacceptable, the programmer can explicitly call
finalize.  IMHO, that decision should be the application programmer's,
not the language designer's.

> Yes, it introduces non-determinism, but if you have non-determinism
> anyway, then this isn't a problem.  :)  (I'd probably have a thread
> that sits there to run finalizers.  After GC completes, it'd move
> finalizers that need to be run from the registered finalizer list to
> the ready to run queue.  The GC would then return immediately, and
> finalizers run in the background.)

So finalizers can not only be run at a non-deterministic time, but they
can run in parallel with the rest of the program.  They could presumably
run in parallel with each other, too -- I don't see any reason why you
couldn't just as well have *several* threads that sit there running
finalizers.  Clearly, the programmer needs to be aware of this.  A
program that *looks* like a purely sequential program is really
multi-threaded, and finalizers will need to lock data structures
accordingly.  Likewise, any code that touches the same data as the
finalizers needs to lock things.

> I'd call it a `programming error' to write a program that has a loop
> of finalizer objects.  ;) I don't have enough experience with
> finalizers to make this judgement, however.  :( 

A run-time error?  Can the program recover (i.e. by handling an
exception)?  Presumably, the error is detected whenever the gc happens
to notice it, rather than immediately upon the creation of the loop.  If
it's an exception, it's not clear which thread ought to be notified.
Or, are you saying that you have compile-time rules to prevent cycles?

> My intended use of finalizers in this OO language, however, is not for
> loops: it is for `containment' of objects.  If a Car contains a Tire,
> then the finalizer for Car might do something to Tire.  It's not for
> `refers to' fields of objects.  If a Car refers to its Owner, the
> owner is not part of the car; the finalizer should not do anything to
> the owner.  In such a system, there can be no loops, and chains can be
> bounded statically (because no object would contain an object of the
> same class, even though it may refer to an object of the same class).

It seems to me that "containment" does not logically preclude an object
from containing another object of the same class.  A tree can reasonably
be thought of as containing subtrees, rather than referring to subtrees.
To me, "contains" requires no cycles, but allows a Foo to contain a
different Foo.

- Bob