* Trying to understand Ada.Finalization.Controlled assignment mechanics. @ 2014-09-23 0:43 Jeremiah 2014-09-23 1:17 ` Jeffrey Carter 0 siblings, 1 reply; 9+ messages in thread From: Jeremiah @ 2014-09-23 0:43 UTC (permalink / raw) My understanding of assignment of a child of Ada.Finalization.Controlled is that if you do the following: A := B; -- A and B are derived from Ada.Finalization.Controlled That the following occurs: Finalize(A); Copy B into A; Adjust(B); Is this correct? I've been learning/relearning Ada lately, so I have been mainly making programs to get a better understanding of the mechanics of Ada. In order to understand assignment, I made a quick tester class. It isn't very useful nor is it meant to be, but it highlights something that I don't understand. test_class2.ads ---------------------------------- with Ada.Finalization; package test_class2 is type access_type is access Integer; type test is new Ada.Finalization.Controlled with record ref : access_type := null; end record; function Make(a : access_type) return test; overriding procedure Adjust(self : in out test); overriding procedure Finalize(self : in out test); end test_class2; test_class2.adb -------------------------- with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; package body test_class2 is function Make(a : access_type) return test is begin return (Ada.Finalization.Controlled with ref => a); end Make; overriding procedure Adjust(self : in out test) is begin Put_Line("Adjusting"); self.ref := null; end Adjust; overriding procedure Finalize(self : in out test) is procedure Free is new Ada.Unchecked_Deallocation(Integer, access_type); begin Put("Finalizing"); if(self.ref /= null) then Put(" (FREED)"); Free(self.ref); end if; New_Line; end Finalize; end test_class2; Main.adb -------------------------- with Ada.Text_IO; use Ada.Text_IO; with test_class2; procedure Main is tester : test_class2.test := test_class2.Make(new Integer'(45)); begin Put_Line("Hello World"); end Main; The output I am seeing doesn't make sense to me: Adjusting Finalizing (FREED) Adjusting Finalizing Hello World Finalizing I wouldn't expect the Freeing of memory to happen until after Hello World when tester goes out of scope. I also thought that Finalize happens before Adjust, but Adjust looks like is happening first. I am compiling and running this on GNAT GPL for windows if that makes a difference. I don't have a different hardware platform to test on. Can anyone explain to me why the "freeing" of memory happens prior to Hello World and whey Adjusting happens before Finalization? I figure I have something fundamental that I am missing. Thanks! ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Trying to understand Ada.Finalization.Controlled assignment mechanics. 2014-09-23 0:43 Trying to understand Ada.Finalization.Controlled assignment mechanics Jeremiah @ 2014-09-23 1:17 ` Jeffrey Carter 2014-09-23 16:08 ` Jeremiah 0 siblings, 1 reply; 9+ messages in thread From: Jeffrey Carter @ 2014-09-23 1:17 UTC (permalink / raw) On 09/22/2014 05:43 PM, Jeremiah wrote: > My understanding of assignment of a child of Ada.Finalization.Controlled is that if you do the following: > > A := B; -- A and B are derived from Ada.Finalization.Controlled > > That the following occurs: > Finalize(A); > Copy B into A; > Adjust(B); > > Is this correct? Not necessarily. This is an assignment statement. ARM 7.6(17) says '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. As explained below, the implementation may eliminate the intermediate anonymous object, so this description subsumes the one given in 5.2, “Assignment Statements”.' So it could be Create C (the anonymous object); Copy B into C; Adjust (C); Finalize (A); Copy C into A; Adjust (A); Finalize (C); If the anonymous object is optimized away, then it becomes your sequence. > tester : test_class2.test := test_class2.Make(new Integer'(45)); > > The output I am seeing doesn't make sense to me: > Adjusting > Finalizing (FREED) > Adjusting > Finalizing > Hello World > Finalizing Your test example is complicated by the use of the function and the aggregate inside it. Someone with a better understanding of GNAT's handling of controlled objects should probably comment on this. But it might be a good idea to start with a simpler test case, involving no initialization, functions, aggregates, or access types, and then complicate it step by step. ARM 7.6(17.1/3) says 'When a function call or aggregate is used to initialize an object, the result of the function call or aggregate is an anonymous object, which is assigned into the newly-created object.' My guess is that there are both an aggregate object and function return object. The aggregate object is copied into the function return object (FRO), the FRO is adjusted, and the aggregate object is finalized. The the FRO is copied into Tester, Tester is adjusted, and the FRO is finalized. The body of the main procedure is then executed, and Tester is finalized. But I could be way off. http://www.adaic.org/resources/add_content/standards/12rm/html/RM-7-6.html -- Jeff Carter "Blessed are they who convert their neighbors' oxen, for they shall inhibit their girth." Monty Python's Life of Brian 83 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Trying to understand Ada.Finalization.Controlled assignment mechanics. 2014-09-23 1:17 ` Jeffrey Carter @ 2014-09-23 16:08 ` Jeremiah 2014-09-23 16:23 ` Adam Beneschan ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: Jeremiah @ 2014-09-23 16:08 UTC (permalink / raw) On Monday, September 22, 2014 9:17:18 PM UTC-4, Jeffrey Carter wrote: > On 09/22/2014 05:43 PM, Jeremiah wrote: > > > tester : test_class2.test := test_class2.Make(new Integer'(45)); > > > > > > The output I am seeing doesn't make sense to me: > > > Adjusting > > > Finalizing (FREED) > > > Adjusting > > > Finalizing > > > Hello World > > > Finalizing > > > > Your test example is complicated by the use of the function and the aggregate > > inside it. Someone with a better understanding of GNAT's handling of controlled > > objects should probably comment on this. But it might be a good idea to start > > with a simpler test case, involving no initialization, functions, aggregates, or > > access types, and then complicate it step by step. > > > > ARM 7.6(17.1/3) says > > > > 'When a function call or aggregate is used to initialize an object, the result > > of the function call or aggregate is an anonymous object, which is assigned into > > the newly-created object.' > > > > My guess is that there are both an aggregate object and function return object. > > The aggregate object is copied into the function return object (FRO), the FRO is > > adjusted, and the aggregate object is finalized. The the FRO is copied into > > Tester, Tester is adjusted, and the FRO is finalized. The body of the main > > procedure is then executed, and Tester is finalized. But I could be way off. > > > > http://www.adaic.org/resources/add_content/standards/12rm/html/RM-7-6.html > It does complicate things, and in the simpler case (using a Set procedure), it does highlight a misunderstanding of mine. I incorrectly assumed Adjust would occur on B, when based on your response and rereading the RM section a few times, Adjust occurs on A instead. Am I understanding that correctly? If so, then this would explain what I am seeing as I am setting the target to null and not nulling the previous object (which is the reverse of what I previously understood). TLDR version (barring the actual complexities you noted above): I previously thought: A := B Finalize(A) copying B into A Adjust(B) But in reality it is closer to: Finalize(A) copying B into A Adjust(A) Again, not taking into account the complexities of FRO's and Anonymous Objects. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Trying to understand Ada.Finalization.Controlled assignment mechanics. 2014-09-23 16:08 ` Jeremiah @ 2014-09-23 16:23 ` Adam Beneschan 2014-09-23 17:39 ` Simon Wright 2014-09-23 17:50 ` Jeffrey Carter 2014-09-23 19:19 ` Robert A Duff 2 siblings, 1 reply; 9+ messages in thread From: Adam Beneschan @ 2014-09-23 16:23 UTC (permalink / raw) On Tuesday, September 23, 2014 9:08:39 AM UTC-7, Jeremiah wrote: > Am I understanding that correctly? If so, then this would explain what I am seeing as I am setting the target to null and not nulling the previous object (which is the reverse of what I previously understood). > > TLDR version (barring the actual complexities you noted above): > I previously thought: > A := B > Finalize(A) > copying B into A > Adjust(B) > > But in reality it is closer to: > Finalize(A) > copying B into A > Adjust(A) > > Again, not taking into account the complexities of FRO's and Anonymous Objects. Yes, you've got it right. If you say "A := B;", B is not modified at all. B could be a constant, in fact, and it could be located in read-only memory. (An Adjust(B) call would try to modify B.) Although Adjust can be used for a number of things, one of the most common cases is to make a copy of pointed-to data. Say the record type has a field Data that is an access type to some array. Say you don't want two records of the same type pointing to the exact same array, but instead you want to make a copy of the array when you create a new object of the type. That's where Adjust comes in. When you say A := B, the program will copy B into A, which means they temporarily have an access (pointer) to the same data. The Adjust procedure would then allocate a new array, make a copy of it, and leave A's Data pointing to the new array. (It doesn't modify B's data pointer at all, and you wouldn't want to, even if B weren't constant.) The Finalize procedure would deallocate the array. Assuming that the record type is private so that outside packages can't modify the Data pointer directly, this will ensure that each record points to its own copy of the array, and that there will not be any dangling pointers to deallocated arrays, unless the outside code does something underhanded like Unchecked_Conversion or something. -- Adam ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Trying to understand Ada.Finalization.Controlled assignment mechanics. 2014-09-23 16:23 ` Adam Beneschan @ 2014-09-23 17:39 ` Simon Wright 0 siblings, 0 replies; 9+ messages in thread From: Simon Wright @ 2014-09-23 17:39 UTC (permalink / raw) Adam Beneschan <adambeneschan@gmail.com> writes: > The Adjust > procedure would then allocate a new array, make a copy of it, and > leave A's Data pointing to the new array .. allocate a new array, copy B's data into it, and leave ... ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Trying to understand Ada.Finalization.Controlled assignment mechanics. 2014-09-23 16:08 ` Jeremiah 2014-09-23 16:23 ` Adam Beneschan @ 2014-09-23 17:50 ` Jeffrey Carter 2014-09-23 19:19 ` Robert A Duff 2 siblings, 0 replies; 9+ messages in thread From: Jeffrey Carter @ 2014-09-23 17:50 UTC (permalink / raw) On 09/23/2014 09:08 AM, Jeremiah wrote: > > I previously thought: > A := B > Finalize(A) > copying B into A > Adjust(B) I must have misread that. Adjust is always called on the target of assignment (A in this case). As Beneschan pointed out, B could be constant. > But in reality it is closer to: > Finalize(A) > copying B into A > Adjust(A) In the case where the anonymous temporary is optimized away, this is what happens. -- Jeff Carter "All citizens will be required to change their underwear every half hour. Underwear will be worn on the outside, so we can check." Bananas 29 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Trying to understand Ada.Finalization.Controlled assignment mechanics. 2014-09-23 16:08 ` Jeremiah 2014-09-23 16:23 ` Adam Beneschan 2014-09-23 17:50 ` Jeffrey Carter @ 2014-09-23 19:19 ` Robert A Duff 2014-09-23 21:59 ` Jeremiah 2 siblings, 1 reply; 9+ messages in thread From: Robert A Duff @ 2014-09-23 19:19 UTC (permalink / raw) Jeremiah <jeremiah.breeden@gmail.com> writes: > Finalize(A) > copying B into A > Adjust(A) Right. It might help to look at some examples. Maybe take a look at the GNAT implementation of Ada.Containers.Vectors, in a-convec.ad* . - Bob ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Trying to understand Ada.Finalization.Controlled assignment mechanics. 2014-09-23 19:19 ` Robert A Duff @ 2014-09-23 21:59 ` Jeremiah 2014-09-24 10:59 ` AdaMagica 0 siblings, 1 reply; 9+ messages in thread From: Jeremiah @ 2014-09-23 21:59 UTC (permalink / raw) Thanks everyone for the responses On Tuesday, September 23, 2014 3:19:52 PM UTC-4, Robert A Duff wrote: > Jeremiah writes: > > > > > Finalize(A) > > > copying B into A > > > Adjust(A) > > > > Right. > > > > It might help to look at some examples. Maybe take a look at the > > GNAT implementation of Ada.Containers.Vectors, in a-convec.ad* . > > > > - Bob Thank you, I will. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Trying to understand Ada.Finalization.Controlled assignment mechanics. 2014-09-23 21:59 ` Jeremiah @ 2014-09-24 10:59 ` AdaMagica 0 siblings, 0 replies; 9+ messages in thread From: AdaMagica @ 2014-09-24 10:59 UTC (permalink / raw) On Tuesday, September 23, 2014 11:59:29 PM UTC+2, Jeremiah wrote: > Thanks everyone for the responses For a very detailed analysis of controlledness, you are invited to look at my page http://www.christ-usch-grein.homepage.t-online.de/AdaMagica/Secretive.html ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-09-24 10:59 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-09-23 0:43 Trying to understand Ada.Finalization.Controlled assignment mechanics Jeremiah 2014-09-23 1:17 ` Jeffrey Carter 2014-09-23 16:08 ` Jeremiah 2014-09-23 16:23 ` Adam Beneschan 2014-09-23 17:39 ` Simon Wright 2014-09-23 17:50 ` Jeffrey Carter 2014-09-23 19:19 ` Robert A Duff 2014-09-23 21:59 ` Jeremiah 2014-09-24 10:59 ` AdaMagica
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox