Solution to finalisation problem [Re: fork()]

Tim Peters tim_one at email.msn.com
Tue Jun 15 02:54:30 CEST 1999


[Greg Ewing]
> Indeed, which leads me to believe that the idea of giving objects
> a __del__ method is fundamentally flawed in the first place.

[Tim]
> Except it works so nice in "the usual" case (no cycle, no resurrection):
> everyone agrees on what should be done then, and it's remarkably
> surprise-free!

[Graham Matthews]
> The problem with this argument

Thought of it as an observation; unless there's some argument about what to
do in the absence of cycles that everyone has been too shy to make here
<wink>.

> Tim is that is is very difficult for the programmer to recognise when
> they are in "the usual case", since circular references are easy to
> create. Hence it is very difficult for the programmer to verify the
> correctness of their code.

"is" is too strong in both cases.  "can be" I'll buy.  In the majority of
classes I've written or seen, it's obvious that instances can never be part
of a cycle -- or, more rarely, obvious that they can be.  Does get muddier
over time with "big classes", though (e.g., the implementation of IDLE
appears to be growing more cyclic relations over time, and that's not
unusual).

> ...
> No cycles are not the problem. The problem is that finalisers are run in
> "incomplete contexts".

*A* problem I buy; not "the".

> These incomplete contexts arise because implementations of GC delete
> or partially delete collected objects before calling finalisers.
> That is a mistake.

Insert "some" after "because" & I agree.

> If you run *all* finalisers of *all* collected objects before you
> actually delete or partially delete any of those objects then all
> finalisers run in well defined contexts and there are no problems
> with finalisers.

Sure there are:  finalizers in cycles remain largely useless in practice
without a way to specify the order in which they're invoked.  Go back to the
Java part of the thread.  The language can't know whether a cycle needs to
be finalized in a particular order, or, if it does, what that order may be.
In Java this has nothing to do with partial deletion:  the spec is very
clear that the implementation must guarantee that all objects reachable from
a finalizer are wholly intact when the finalizer is run.  What it doesn't
say-- because it can't --is that all objects reachable from a finalizer will
be in a "useful" state.  That's left on the programmer's head, and when e.g.
child and parent can be finalized in either order or even simultaneously,
correct non-trivial finalizers are jokingly difficult to write.

The Scheme guardian gimmick at least attempts to address this, by never
finalizing anything by magic, leaving it up to the programmer to explicity
ask for an enumeration of the currently-finalizable objects and nuking them
or not however the programmer sees fit.  If a cycle needs special treatment,
it's up to the programmer to realize that a cycle exists and "do the right
thing" by their own lights.  The language doesn't help, but at least it
doesn't get in the way by doing a wrong thing either; it simply doesn't do
anything at all.

> That is the point of two pass collection.

Understood the first time; but if finalizers are to be invoked on cycle
members, that's just necessary, not sufficient.

a-problem-isn't-solved-until-the-users-agree-ly y'rs  - tim






More information about the Python-list mailing list