🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.clos
Article #367

destructors in CLOS?

#367
From: Jon L White
Date: Thu, 20 Dec 1990 06:51
127 lines
7392 bytes
re: I would like to define a method that gets called when a CLOS instance
    gets garbage collected, sort of like a destructor method in c++.

    Can I do this in CLOS?  How?


This question has been asked several times in the past year, the most
recent two instances of which are Eero Simoncelli's query to this very
list last summer, and Roman Cunis's question raised at the CLOS workshop
during ECOOP/OOPSLA '90 last October.

Here is Eero's query, and the only reply to it that I ever saw:

    Date: Wed, 18 Jul 90 16:46:49 PDT
    From: eero@newton.arc.nasa.gov (Eero Simoncelli)
    To: CommonLoops.PA@Xerox.COM
    Subject: Any plans for a finalize-instance method?

    Are there any plans to incorporate a "finalize-instance" method
    (complementing the initialize-instance method) in the CLOS spec?  This
    method would be called after the instance was orphaned (i.e.  all
    references destroyed), but before it was garbage-collected.
    Obviously, this requires an implementation-dependent hook into the
    garbage-collection process.  This would allow cleanup of allocated
    foreign or system structures, static data resources, etc.

    Eero.

    Date: Wed, 18 Jul 90 20:01:39 PDT
    From: smh@franz.com (Steve Haflich)
    To: eero@newton.arc.nasa.gov
    . . .
    Franz's 4.0 release will provide object finalization, as do some other
    implementations, but I doubt X3J13 would agree to require it in the
    language spec on two grounds: First, . . .


At the CLOS workshop, I mentioned that Lucid has developed a finalization
technique independent of CLOS and that it would likely be in the next
release (I have had experimental versions running for some time now, but
I'm not authorized to make product announcements; the current released
product, Lucid 4.0, reached design closure last Spring, and doesn't have
this code in it.)  Chris Richardson, from Franz Inc., also mentioned that
Franz had been working on a finalization technique that would be released
in their upcoming 4.0 version, which he said would be due out in January
or February 1991.

However, you need to compare what "finalization" is likely to mean in
implementations that are not doing true "garbage" collection.  At the
very least, it will not likely be as simple as merely placing a method on
FINALIZE-INSTANCE -- probably it will require some individual registration
of the objects to be finalized, which could be done on a per-class basis
by an initialization(!) method.   In practice, it may feel as simple as a
defmethod, but there are couple of differences that can be observed by
judicious test cases.  This is why I said that "finalization" will be
independent of CLOS.  But of course CLOS objects will be finalizable just
like any other stored-memory object will be; Steve Haflich, in his reply
to Eero above, also stressed this point.

Also, you should be aware of the slight difference between "destructor"
and "finalization"; the former is the code that actually "disassembles"
some no-longer useful object, whereas the latter is the process of
identifying which objects that the "Garbage Collection" process, or
the "Garbage Abandonment" process, should tickle upon when such an object
is discovered to be abandoned.  In the current C++ world, there is no
automatic memory management, so the end-user code itself must invoke
the destructor.  Furthermore, the "destructor" code might typically try
to recycle the space consumed by the object being "destroyed" (such as
by placing it back in a pool of available such objects); but in Lisp,
of course, you typically wouldn't try to thread the piece of garbage
back into a live pool, but would rather let the next cycle of GC pick
it up (on the other hand, you might do it anyhow!)

It is worth noting that some of the participants in the Garbage
Collection Workshop at ECOOP/OOPSLA '90 (myself included) are currently
actively disussing how garbage collection *might* be added to C++.
There is definitely some very serious concern by the more C-oriented
folks in that group that "finalization" (as opposed to destructors) can
never be a precise process.  First, in the worst case scenario, the
C++ world might not be able to tolerate "complete GC" -- that is, they
may be reduced to coexisting with so-called "conservative" garbage
collectors, whose contract is merely that they will (1) try hard to
collect some garbage, (2) and never collect any living structures,
(3) but leave open some reasonable paths in which particular pieces of
garbage  will never be collected, even though the user's program has
dropped all pointers to them.  So it is possible that the requirement
for precise finalization may rule out some otherwise important GC
techniques.

This concern about the ability to prove that something is in fact
garbage can even spill over into the Lisp world.  For example, an
optimizing Lisp compiler will probably use temporary registers in
such a way that a pointer may appear to be "alive" even after the
user's code has just smashed out the last copy of it in his own
data structures.  This seems to be a fact of "life in the big city",
both in the Lisp world and in the C world.  It may not be possible
to reclaim a dead object until you exit from the last function
frame that was referencing it.

Finally, the question arises of just how urgent the demand to
"finalize" a given object must be.  How many seconds after dropping
the last pointer to the object are you willing to wait until the
destructor code is executed?  In Interlisp-D (and presumably in the
Common Lisp product that came out of it in latter years, now marketed
by a company called Venue), this was essentially not a problem, because
it used a reference-counting GC; and usually within a very short time
of the reference count being decremented to zero, there would be an
incremental collection that would run the associated destructor code.
That is, you wouldn't have to wait until consing activity crossed
some threshold and triggered a GC, or until you explicitly called
GC from user code; the reference-counting and incremental triggering
was sufficient.

[Yea, Interlisp-D had a form of finalization back in the early 1980's,
and I even put it into PDP10 MacLisp in the early 1970's for just the
reasons that Eero mentioned above.  But what neither system offered
was a mechanism for the end-user to hook his own datatypes up for
finalization.  These earlier versions were specifically hooked only
to certain system datatypes that connected to "system" data-structures.
Oh yes, I recall the lacuna in the earlier versions of Interlisp-D
where the incremental GC didn't scavenge everything available; we
would have to do something like (RPTQ 20 (GC)) in order to assure
that the last bit of garbage got "licked up".  But I'm fairly certain
that that gap was later plugged.]


-- JonL --
Technical Details
Message-ID: <9012200651.AA00980@caligula>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!tut.cis.ohio-state.edu!LUCID.COM!jonl
References: <CREON.90Dec18151709@wk39.nas.nasa.gov>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!tut.cis.ohio-state.edu!LUCID.COM!jonl
From: jonl@LUCID.COM (Jon L White)
Newsgroups: comp.lang.clos
Subject: destructors in CLOS?
Message-ID: <9012200651.AA00980@caligula>
Date: 20 Dec 90 06:51:08 GMT
References: <CREON.90Dec18151709@wk39.nas.nasa.gov>
Sender: welch@tut.cis.ohio-state.edu
Distribution: inet
Organization: CommonLoops
Lines: 127