comp.lang.ada
 help / color / mirror / Atom feed
From: "Frank J. Lhota" <lhotaf@lexma.meitech.com>
Subject: Finalization and Self Assignment
Date: 2000/02/29
Date: 2000-02-29T00:00:00+00:00	[thread overview]
Message-ID: <ueTu4.52$kE4.1111@client> (raw)

I find the Ada controlled object facility to be a convenient mechanism for
controlling the initialization, assignment, and finalization of an object.
There is a potential problem with this facility, however, that needs to be
addressed: what happens when a variable is assigned to itself? Obviously, no
one writes statements like "x := x;" in real programs, but self assignment
can occur in boundary cases for reasonable assignments such as

    List (I) := List (J);

when I equals J, or

    This_Ptr.all := That_Ptr.all;

when This_Ptr and That_Ptr are the same access values. Self assignment is
generally a non-op, and may never do anything terribly useful. Still it
should not be a dangerous operation, and unfortunately it can undermine
finalization and adjustments.

For example, assume that we are implementing an object whose memory
requirements varies widely. We could represent the object using access
values, and use the Finalization package to do the pointer maintenance:

    type My_Object_Implementation ( Length : Natural ) is record ... end
record;
    type My_Object_Implementation_Ptr is access all
My_Object_Implementation;

    type My_Object is new Ada.Finalization.Controlled with
        record
            Ptr : My_Object_Implementation_Ptr;
            ...
        end record;

With this scheme, the Initialize procedure would allocate initial values for
the pointers, the Finalize procedure would deallocate the pointers, and the
Adjust procedure would make independent copies of the pointer data. All of
this works fine, as long as no object is assigned to itself. If self
assignment does the finalization / adjust sequence, however, this scheme
falls apart. For example:

    x : My_Object;
    ...
    x := x;

If the assignment statement invokes Finalization on x, we will have
destroyed the data in both the source and the target in the assignment. This
is not a problem that can be fixed in the Adjust phase; by then, the data is
gone. The object is now ruined, in an operation that should have had no
effect on x.

What if we used a reference count? We would still have a problem in the
common case where x points to something with a reference count of 1. In this
case, Finalize would decrement the reference count, and finding a reference
count of 0, deallocate x.Ptr. Once again, our effort to clean up the target
of the assignment ends up destroying the source.

Fortunately, on many platforms, self assignment is not an issue. Ada RM
7.6(19) allows the following implementation permission in regards to the
assignment of controlled objects:

- For an assignment_statement that assigns to an object the value of that
same object, the implementation need not do anything.

ObjectAda as well as some (all?) versions of GNAT take advantage of this
permission. I would recommend that this permission be promoted to a
requirement. In other words, we should require that the compiler NOT do the
Finalize / Adjust calls when an object is assigned to itself. The issue here
is not so much efficiency as it is correctness. If we simply eliminate the
Finalize / Adjust calls from self assignments, these problems go away.










             reply	other threads:[~2000-02-29  0:00 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-02-29  0:00 Frank J. Lhota [this message]
2000-02-29  0:00 ` Finalization and Self Assignment Robert A Duff
2000-03-04  0:00 ` Nick Roberts
2000-03-04  0:00 ` Simon Wright
replies disabled

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