comp.lang.ada
 help / color / mirror / Atom feed
From: Adam Beneschan <adam@irvine.com>
Subject: Re: Question about controlled types.
Date: Thu, 7 Feb 2008 08:47:48 -0800 (PST)
Date: 2008-02-07T08:47:48-08:00	[thread overview]
Message-ID: <f063ec6a-86d1-42d9-b8bb-055d1de00ba5@m34g2000hsf.googlegroups.com> (raw)
In-Reply-To: 47aa5ca6$0$32487$4d3efbfe@news.sover.net

On Feb 6, 5:19 pm, "Peter C. Chapin" <pcha...@sover.net> wrote:
> I'm trying to understand the subtleties of controlled types. In the RM,
> section 7.6, paragraph 17 (I'm looking at the Ada 2005 version) I see:
>
> "For an assignment_statement, after the name and expression have been
> evaluated, and any conversion (including constraint checking) has been
> done, an anonymous object is created, and the value is assigned into it;
> that is, the assignment operation is applied. (Assignment includes value
> adjustment.) The target of the assignment_statement is then finalized.
> The value of the anonymous object is then assigned into the target of
> the assignment_statement. Finally, the anonymous object is finalized."

Did you read the rest of the paragraph?  "As explained below, the
implementation may eliminate the intermediate anonymous object, so
this description subsumes the one given in 5.2, 'Assignment
Statements'".  If you read the "below" part to which this sentence
refers, in the Implementation Permissions, you'll find that in the
case where an object is assigned to another object (i.e. not a
function call or an aggregate), you really need the intermediate
anonymous object only if there's the possibility of an overlap.
Suppose A is an array of controlled objects, and you say

  A (2 .. 10) := A (1 .. 9);

Now a compiler might well decide to create a temporary object to hold
the array slice being assigned, because it will have to finalize
elements A(2) through A(9) before assigning them, and it will have to
store those values somewhere before doing that finalization.  (Even in
that case, the temporary object isn't necessary since the compiler
could generate code to copy one element at a time.)



> So suppose we have
>
> type Ptr is access Whatever;
> type Thing is new Ada.Finalization.Controlled with
>    record
>      P : Ptr;
>    end record;
>
> Thus Things hold a handle to an object allocated on the heap. Now
> suppose A and B are Things. Then consider
>
> A := B;
>
> If I understand the paragraph above, an anonymous object is created and
> the values of B's components are copied into that object.

Based on the Implementation Permission, I will bet that *no* compiler
will actually create an anonymous temporary object.  A and B can't
overlap unless they're the same object (possible if one of them is a
subprogram parameter), and in that case the compiler could simply
generate code to check the addresses and see if they're the same
object.

> Adjust is then
> used on the anonymous object. Let's imagine that Adjust makes an
> independent copy of the object accessed via the P component. If an
> exception occurs during this adjustment (Storage_Error, say) the value
> of A is not affected. This is good.
>
> Next A is finalized and then the anonymous object is then assigned to A.
> Here is my question: is Adjust used again to adjust the value of A? It
> would seem so because the anonymous object is finalized after this and
> we wouldn't want that finalization to disrupt A's eventual value (assume
> Finalize deallocates the object accessed by the P component). However,
> if that is all true then why use Adjust on the anonymous object?
>
> It seems to me that a more appropriate sequence of events would be
>
> 1. Create the anonymous object as above (using Adjust, etc).
> 2. Finalize A as above.
> 3. Copy the components of the anonymous object to A without using Adjust.
> 4. Don't Finalize the anonymous object.

The trouble is, you're thinking about one particular use of controlled
types, where Adjust's sole purpose is to make a copy of the data
pointed to by a pointer (or multiple pointers).  That's a common use,
but not the only possible use.  Although I can't immediately think of
an example where your sequence would screw things up, the AARM refers
to subcomponents that are "self-referential or otherwise position-
dependent" (I think Hyman was referring to this same notion here).


> My concern here is exception safety. I'd like it to be the case that
> when I do
>
> A := B;
>
> if there is insufficient memory to build a proper copy of B's complete
> representation (including heap structures), I'd like A to be left
> unchanged. Yet the semantics described in the RM seem to say that A will
> be finalized (thus destroying its value) before the copy of B that
> eventually gets stored in A is made. Thus if that copy operation fails
> with Storage_Error, A is left corrupted.
>
> This question seems very relevant to the Ada 2005 container library. For
> example if A and B are vectors, and if B is a very large vector that I'm
> trying to copy, I'd really like for A to be left unchanged should
> Storage_Error occur during that copy.

Like I said above, A := B probably isn't going to involve an anonymous
object at all, because of the Implementation Permissions in this
section.  This means that A will be finalized before any attempt is
made to copy the structure pointed to by B; if your idea is that A
must be unchanged if the copy of B could raise a Storage_Error, then
you'll probably have to roll your own:

    procedure Safe_Assign (A : in out Thing; B : in Thing) is
       Temp : Thing;
    begin
       Temp := B;
       A.Ptr := Temp.Ptr;
       Temp.Ptr := null;
    end Safe_Assign;

I'll admit that that probably won't help with the container library,
though.

                               -- Adam



  parent reply	other threads:[~2008-02-07 16:47 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-07  1:19 Question about controlled types Peter C. Chapin
2008-02-07  4:54 ` Hyman Rosen
2008-02-07 16:30   ` Robert A Duff
2008-02-08  3:31     ` Peter C. Chapin
2008-02-08  3:47   ` Peter C. Chapin
2008-02-07 16:47 ` Adam Beneschan [this message]
2008-02-08  3:46   ` Peter C. Chapin
replies disabled

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