From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,f5508b044317ceed,start X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news2.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nx01.iad01.newshosting.com!newshosting.com!198.186.190.251.MISMATCH!transit4.readnews.com!news-out.readnews.com!postnews3.readnews.com!not-for-mail Date: Wed, 06 Feb 2008 20:19:32 -0500 From: "Peter C. Chapin" User-Agent: Thunderbird 2.0.0.9 (Windows/20071031) MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Question about controlled types. Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Message-ID: <47aa5ca6$0$32487$4d3efbfe@news.sover.net> Organization: SoVerNet (sover.net) NNTP-Posting-Host: 8e763563.news.sover.net X-Trace: DXC=mhm8k@5;ZcnbZ<<3De[fciK6_LM2JZB_cZ@<5Vh0c35c3?@`i3kGa5kQ60= 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." 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. 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. 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. Peter