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=0.2 required=5.0 tests=BAYES_00,INVALID_MSGID, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,37d1760a19f7ae57 X-Google-Attributes: gid103376,public From: "Norman H. Cohen" Subject: Re: Q. on Automatic Package Finalization Date: 1996/10/04 Message-ID: <325531FC.82B@watson.ibm.com>#1/1 X-Deja-AN: 187541099 references: content-type: text/plain; charset=us-ascii organization: IBM Thomas J. Watson Research Center mime-version: 1.0 reply-to: ncohen@watson.ibm.com newsgroups: comp.lang.ada x-mailer: Mozilla 3.0 (Win95; I) Date: 1996-10-04T00:00:00+00:00 List-Id: Robert Dewar wrote: > Really the annoying thing is the restriction on controlled typs to the > outer level. This really is not something that the compilre requires. We > may provide some facility in GNAT to get around this restriction ... Unfortunately, the restriction is necessary to prevent dangling references: with Ada.Finalization; use Ada.Finalization; package Long_Lived is type Controlled_Pointer_Type is access Controlled'Class; Stale_Pointer_1, Stale_Pointer_2: Controlled_Pointer_Type; end Long_Lived; with Ada.Finalization, Long_Lived; use Ada.Finalization; procedure Local_Scope is Short_Lived_Variable: Integer := 0; package Nested_Finalization is type Nested_Controlled is new Controlled with null record; -- ILLEGAL! procedure Finalize (Object: in out Nested_Controlled); end Nested_Finalization; package body Nested_Finalization is procedure Finalize (Object: in out Nested_Controlled) is begin Short_Lived_Variable := Short_Lived_Variable + 1; end Finalize; end Nested_Finalization; begin Long_Lived.Stale_Pointer_1 := new Nested_Finalization.Nested_Controlled; Long_Lived.Stale_Pointer_2 := new Nested_Finalization.Nested_Controlled; end Local_Scope; with Long_Lived, Local_Scope; procedure Main is begin Local_Scope; -- Sets Stale_Pointer_1 and Stale_Pointer_2 to point to objects of a -- type Nested_Controlled that no longer exists upon return from the call. Long_Lived.Stale_Pointer_1.all := Long_Lived.Stale_Pointer_2.all; -- Invokes the Finalize procedure for Stale_Pointer_1.all, which increments -- Short_Lived_Variable, but Short_Lived_Variable no longer exists! end Main; Nonetheless, there are legitimate implementation-defined enhancements to achieve the effect of frame finalization that manipulates local variables. One approach would be a generic package Nested_Finalization whose instances provide facilities identical to those of Ada.Finalization, but using their own root types Controlled and Limited_Controlled and, like Ada.Finalization, achieving the required effect through invisible implementation magic. Nested_Finalization could be instantiated inside a subprogram, for example, and extended there: with Nested_Finalization; procedure Local_Scope is package Local_Finalization is new Nested_Finalization; package Frame_Finalization is type Frame_Finalization_Type is new Local_Finalization.Controlled with ...; -- Legal because the parent type is at same accessibility level. ... procedure Finalize (Object: in out Frame_Finalization_Type); end Frame_Finalization; ... Frame_Finalization_Object: Frame_Finalization_Type; begin ... end Local_Scope; A simpler alternative for frame finalization is the following generic package: generic with procedure Finalize; package At_End; Instantiation of this package within a frame's declarative part would, through invisible implementation magic, cause the procedure Finalize to be invoked upon exit from the frame: with At_End; procedure Local_Scope is ... procedure My_Finalize is ... end My_Finalize; package Frame_Finalization is new At_End(My_Finalize); begin ... end Local_Scope; -- Norman H. Cohen mailto:ncohen@watson.ibm.com http://www.research.ibm.com/people/n/ncohen