comp.lang.ada
 help / color / mirror / Atom feed
From: bobduff@world.std.com (Robert A Duff)
Subject: Re: Finalization and Garbage Collection: a hole in the RM?
Date: 1996/08/29
Date: 1996-08-29T00:00:00+00:00	[thread overview]
Message-ID: <DwwuKz.Kv4@world.std.com> (raw)
In-Reply-To: mazzanti-2608961026160001@mac-mazz.iei.pi.cnr.it


In article <mazzanti-2608961026160001@mac-mazz.iei.pi.cnr.it>,
Franco Mazzanti <mazzanti@iei.pi.cnr.it> wrote:
>I could not find are rule describing what could/should happen when an
>exception is raised by a Finalization routine called by the garbage
>collector. ...

There are many nasty interactions between garbage collection and
finalization.  What to do with exceptions is one of them.  Others are:
Since the gc is essentially running concurrently with the user's
task(s), how to prevent race conditions?  In what order should the gc
invoke finalization on garbage objects?  (If A points to B, you would
normally want B finalized first, but what about cycles?)  What happens
if some objects are found to be garbage, and then a finalizer resurrects
some of them, by planting some pointers to them in non-garbage objects?

This stuff was discussed extensively a while back on the gclist mailing
list, which I'll post about in another note.  I don't remember if the
exception issue was discussed.  There's an ftp site for copies of old
stuff.

One possible answer is that the exceptions get lost, as for a task.
This makes debugging rather painful.

Another possibility is to kill the whole program, trap into the
debugger, record the error in an error log, or whatever is appropriate
for catastrophic failures on your system.

Another possibility is to not collect finalizable objects.  This is
probably the easiest to implement -- the implementation will probably
attach all the finalizable objects to a per-task linked list, and the
garbage collector will naturally find them on the list, and assume
they're not garbage, unless the gc does something special (like treating
that list like Modula-3 weak pointers).  One possible rationale for this
attitude is, "Most finalization is for deallocating memory anyway, so if
you have gc, why bother?  The remaining finalization is for managing
things like file handles and so forth (i.e. pointers to things outside
the program), and these are mostly stack-allocated things anyway.  In
the rare cases when you have file handles living in heap objects, the
programmer has to worry about it.  Another possible rationale is that
having code that does stuff at unpredictable times is a pain to debug
anyway, so it's better not to mix gc and finalization.  After all, a gc
is supposed to be invisible, except for memory-usage and timing -- the
gc shouldn't go around calling procedures with side effects.  I'm not
sure whether or not I believe these arguments, but they have *some*
merit.

In any case, the design of Ada 95 does not answer your question, so I'd
say it's fair for the gc implementer to design a solution to the
problem.  There's always the cop-out of letting the user choose from
among several bad options.  ;-)

- Bob

P.S. Here's everything the AARM has to say about garbage collection:

7.6.1:

   24.o   Because Controlled and Limited_Controlled are library-level tagged
        types, all controlled types will be library-level types, because of
        the accessibility rules (see 3.10.2 and 3.9.1).  This ensures that
        the Finalize operations may be applied without providing any
        ``display'' or ``static-link.''  This simplifies finalization as a
        result of garbage collection, abort, and asynchronous transfer of
        control.

13.11.3 Pragma Controlled

1   [Pragma Controlled is used to prevent any automatic reclamation of
storage (garbage collection) for the objects created by allocators of a given
access type.]


                                   Syntax

    2   The form of a pragma Controlled is as follows:


3     pragma Controlled(first_subtype_local_name);

        3.a   Discussion:  Not to be confused with type Finalization.-
        Controlled.


                               Legality Rules

4   The first_subtype_local_name of a pragma Controlled shall denote a
non-derived access subtype.


                              Static Semantics

5   {representation pragma [Controlled]} {pragma, representation
[Controlled]} A pragma Controlled is a representation pragma {aspect of
representation [controlled]} {controlled (aspect of representation)} that
specifies the controlled aspect of representation.

6   {garbage collection} Garbage collection is a process that automatically
reclaims storage, or moves objects to a different address, while the objects
still exist.

        6.a   Ramification:  Storage reclamation upon leaving a master is not
        considered garbage collection.

        6.b   Note that garbage collection includes compaction of a pool
        (``moved to a different Address''), even if storage reclamation is
        not done.

        6.c   Reason:  Programs that will be damaged by automatic storage
        reclamation are just as likely to be damaged by having objects moved
        to different locations in memory.  A pragma Controlled should turn
        off both flavors of garbage collection.

        6.d   Implementation Note:  If garbage collection reclaims the
        storage of a controlled object, it should first finalize it.
        Finalization is not done when moving an object; any self-relative
        pointers will have to be updated by the garbage collector.  If an
        implementation provides garbage collection for a storage pool
        containing controlled objects (see 7.6), then it should provide a
        means for deferring garbage collection of those controlled objects.

        6.e   Reason:  This allows the manager of a resource released by a
        Finalize operation to defer garbage collection during its critical
        regions; it is up to the author of the Finalize operation to do so.
        Garbage collection, at least in some systems, can happen
        asynchronously with respect to normal user code.  Note that it is not
        enough to defer garbage collection during Initialize, Adjust, and
        Finalize, because the resource in question might be used in other
        situations as well.  For example:
6.f         with Ada.Finalization;
            package P is

6.g             type My_Controlled is
                    new Ada.Finalization.Limited_Controlled with private;
                procedure Finalize(Object : in out My_Controlled);
                type My_Controlled_Access is access My_Controlled;

6.h             procedure Non_Reentrant;

6.i         private
                ...
            end P;

6.j         package body P is
                X : Integer := 0;
                A : array(Integer range 1..10) of Integer;

6.k             procedure Non_Reentrant is
                begin
                    X := X + 1;
                    -- If the system decides to do a garbage collection here,
                    -- then we're in trouble, because it will call Finalize on
                    -- the collected objects; we essentially have two threads
                    -- of control erroneously accessing shared variables.
                    -- The garbage collector behaves like a separate thread
                    -- of control, even though the user hasn't declared
                    -- any tasks.
                    A(X) := ...;
                end Non_Reentrant;

6.l             procedure Finalize(Object : in out My_Controlled) is
                begin
                    Non_Reentrant;
                end Finalize;
            end P;

6.m         with P; use P;
            procedure Main is
            begin
                ... new My_Controlled ... -- allocate some objects
                ...  forget the pointers to some of them, so they become garbage
                Non_Reentrant;
            end Main;

        6.n   It is the user's responsibility to protect against this sort of
        thing, and the implementation's responsibility to provide the
        necessary operations.

        6.o   We do not give these operations names, nor explain their exact
        semantics, because different implementations of garbage collection
        might have different needs, and because garbage collection is not
        supported by most Ada implementations, so portability is not
        important here.  Another reason not to turn off garbage collection
        during each entire Finalize operation is that it would create a
        serial bottleneck; it might be only part of the Finalize operation
        that conflicts with some other resource.  It is the intention that
        the mechanisms provided be finer-grained than pragma Controlled.

7   If a pragma Controlled is specified for an access type with a standard
storage pool, then garbage collection is not performed for objects in that
pool.

        7.a   Ramification:  If Controlled is not specified, the
        implementation may, but need not, perform garbage collection.  If
        Storage_Pool is specified, then a pragma Controlled for that type is
        ignored.

        7.b   Reason:  Controlled means that implementation-provided garbage
        collection is turned off; if the Storage_Pool is specified, the pool
        controls whether garbage collection is done.


                         Implementation Permissions

8   An implementation need not support garbage collection, in which case, a
pragma Controlled has no effect.


                         Wording Changes From Ada 83

        8.a   Ada 83 used the term ``automatic storage reclamation'' to refer
        to what is known traditionally as ``garbage collection''.  Because of
        the existence of storage pools (see 13.11), we need to distinguish
        this from the storage reclamation that might happen upon leaving a
        master.  Therefore, we now use the term ``garbage collection'' in its
        normal computer-science sense.  This has the additional advantage of
        making our terminology more accessible to people outside the Ada
        world.




  reply	other threads:[~1996-08-29  0:00 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1996-08-26  0:00 Finalization and Garbage Collection: a hole in the RM? Franco Mazzanti
1996-08-29  0:00 ` Robert A Duff [this message]
1996-08-29  0:00 ` Robert A Duff
  -- strict thread matches above, loose matches on Subject: below --
1996-08-30  0:00 Franco Mazzanti
1996-08-30  0:00 ` Robert A Duff
1996-09-02  0:00 Franco Mazzanti
1996-09-03  0:00 ` Robert A Duff
1996-09-03  0:00 ` Robert Dewar
1996-09-04  0:00 Franco Mazzanti
1996-09-08  0:00 ` Robert Dewar
1996-09-06  0:00 Franco Mazzanti
1996-09-06  0:00 ` Robert A Duff
1996-09-07  0:00   ` Robert Dewar
1996-09-09  0:00 Franco Mazzanti
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox