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,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 10.107.18.203 with SMTP id 72mr21611191ios.70.1511717629276; Sun, 26 Nov 2017 09:33:49 -0800 (PST) X-Received: by 10.157.39.197 with SMTP id c63mr1540374otb.11.1511717629154; Sun, 26 Nov 2017 09:33:49 -0800 (PST) Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!feeder.eternal-september.org!news.kjsl.com!usenet.stanford.edu!i6no6813438itb.0!news-out.google.com!x87ni4700ita.0!nntp.google.com!193no398860itr.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Sun, 26 Nov 2017 09:33:48 -0800 (PST) In-Reply-To: <6496a10f-c97e-4e42-b295-2478ad464b2f@googlegroups.com> Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=173.71.208.22; posting-account=QF6XPQoAAABce2NyPxxDAaKdAkN6RgAf NNTP-Posting-Host: 173.71.208.22 References: <4db43571-7f86-4e73-8849-c41160927703@googlegroups.com> <6496a10f-c97e-4e42-b295-2478ad464b2f@googlegroups.com> User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <6106dfe6-c614-4fc1-aace-74bf8d7435e3@googlegroups.com> Subject: Re: Extending a third party tagged type while adding finalization From: Jere Injection-Date: Sun, 26 Nov 2017 17:33:49 +0000 Content-Type: text/plain; charset="UTF-8" Xref: feeder.eternal-september.org comp.lang.ada:49165 Date: 2017-11-26T09:33:48-08:00 List-Id: On Wednesday, November 22, 2017 at 11:42:19 AM UTC-5, AdaMagica wrote: > Perhaps this might help you: > > http://www.christ-usch-grein.homepage.t-online.de/Ada/Finalization.html > > I published this in Ada Letters, Volume XIX, Number 4, December 1999. That's similar to what I tried. The only things it didn't cover that my attempt did was 1.) allowing extension on the Finalize 2.) The same for Initialize. What I tried to do was use a mixin but have it keep a reference to a classwide access on the object. Then I tried dispatching out to the correct object type from there. This kind of highlighted the evils of using redispatch in Ada though as I found that if I had component definitions like this: ********************************************************************** package Components is type LC_Component1 is new Ada.Finalization.Limited_Controlled with null record; overriding procedure Initialize(Self : in out LC_Component1); overriding procedure Finalize(Self : in out LC_Component1); type LC_Component2 is new Ada.Finalization.Limited_Controlled with null record; overriding procedure Initialize(Self : in out LC_Component2); overriding procedure Finalize(Self : in out LC_Component2); end Components; package body Components is overriding procedure Initialize(Self : in out LC_Component1) is begin Put_Line("LC1: Initialize"); end Initialize; overriding procedure Finalize(Self : in out LC_Component1) is begin Put_Line("LC1: Finalize"); end Finalize; overriding procedure Initialize(Self : in out LC_Component2) is begin Put_Line("LC2: Initialize"); end Initialize; overriding procedure Finalize(Self : in out LC_Component2) is begin Put_Line("LC2: Finalize"); end Finalize; end Components; ********************************************************************** And I had it so some uncontrolled base type had a component of LC1 while a descendant of my mixin had a component of LC2: ********************************************************************** package Base is type Instance is tagged limited record c1 : Components.LC_Component1; end record; end Base; package LC is new Bullfrog.Limited_Controlled_Mixin(Base.Instance); package Extension is type Instance is new LC.Limited_Controlled with record c2 : Components.LC_Component2; end record; overriding procedure Initialize(Self : in out Instance); overriding procedure Finalize(Self : in out Instance); end Extension; package body Extension is overriding procedure Initialize(Self : in out Instance) is begin Put_Line("Extension: Initialize"); end Initialize; overriding procedure Finalize(Self : in out Instance) is begin Put_Line("Extension: Finalize"); end Finalize; end Extension; ********************************************************************** Then the component c2 would Initialize too late for my solution and it would finalize too early. Output from my test by simply declaring a variable of type Extension.Instance: Starting Test_Limited_Controlled_Mixin LC1: Initialize Extension: Initialize LC2: Initialize LC2: Finalize Extension: Finalize LC1: Finalize So while it is safe to add in the Initialize and Finalize functionality, it isn't safe to do so and also have the ability to make it inheritable for descendants. I'm guessing there may not be a safe way to do it so it'll just have to fall on the descendant to wrap their components in a Finalization type. Based on what I have read so far, I didn't see any discussion that would lead me to think this will be changed at least in the near future. I wish there was a way it would be easy for vendors to do something like: type Some_Type is tagged private; for Some_Type'Initialize use Initialize_Some_Type; for Some_Type'Adjust use Adjust_Some_Type; for Some_Type'Finalize use Finalize_Some_Type; and then just have the compiler handle adding the needed structures to the type under the hood (like how GNAT uses Controlled to hold a linked list under the hood...but compiler managed).