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.3 required=5.0 tests=BAYES_00, 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/09/24 Message-ID: <324837B8.2361@watson.ibm.com> X-Deja-AN: 185090499 references: <523tt4INNlu7@snoopy.cis.ohio-state.edu> 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-09-24T00:00:00+00:00 List-Id: Robert Dewar wrote: > > iDave said > > "Hi. Does anyone know of a good way to achieve automatic package > finalization in Ada95? I'd like to create a generic package which > automatically cleans up its package instance state (possibly including > allocated memory, temporary files, etc.) when the package scope ends. > The code below (which compiles under GNAT 3.05) is one attempt to > achieve this using controlled types. It requires that the > representation of state for package P instances be incorporated into > an instance (pkg_var) of a controlled type (PC.T) declared > in a library-level package (PC). This is not a very satisfactory > solution even if it would work. Does anyone have some better > ideas for handling automatic package finalization?" > > This seems a perfectly reasonable approach, and indeed it was knowing > that this approach existed that made it seem unwise to clutter the language > with yet another feature for handling this case specifically. To be honest, I don't think we realized it would be so complicated during the Ada 9X design reviews. The complication arises from the fact that we would like the finalization of a "frame" (i.e., a block statement or a body) to be able to refer to variables declared locally inside that frame, but the rules about accessibility levels prevent us from doing so. David Gibson's solution--to declare a global template for what should be local data--is clever, but David rightfully regards it as ugly. In other words, not yet being as accustomed as we are today to being bitten by the accessibility rules ;-), we envisioned being able to do something like with Ada.Finalization; procedure P is Local_Variable_1 : T1; Local_Variable_2 : T2; Local_Variable_3 : T3; ... package Frame_Finalization is type Frame_Finalization_Type is new Ada.Finalization.Limited_Controlled -- ILLEGAL! with null record; procedure Finalize (X: in out Frame_Finalization_Type); Frame_Finalization_Object: Frame_Finaliztion_Type; end Frame_Finalization; package body Frame_Finalization is procedure Finalize (X: in out Frame_Finalization_Type) is begin ... -- references to the local variables of P end Finalize; end Frame_Finalization; begin ... -- statements of P, manipulating Local_Variable_1, -- Local_Variable_2, Local_Variable_3, ... end P; (Upon departure from P, as Finalization_Object is about to cease to exist, the Finalize procedure is invoked.) We cannot really do this because it is illegal to extend a library-level type such as Ada.Finalization.Limited_Controlled except at library level (see RM 3.9.1(3)). David Gibson's problem was frame finalization not for a procedure, but for a generic package. He ran into a similar restriction, against extending a library-level type in a generic body (RM 3.9.1(4)). His solution is to declare his controlled type at library level. Instead of declaring a dummy controlled type with no components, he gives the type one record component for each of the local variables that the finalization routine is to manipulate. The finalization routine is rewritten to manipulate the corresponding components of the object being passed to it. The local variables to be finalized are replaced by a single object of the new controlled type. The analog for the procedure P above would be: package P_Wrapper is procedure P; end P_Wrapper; with Ada.Finalization; package body P_Wrapper is package Frame_Finalization is type P_State_Type is new Ada.Finalization.Controlled with record Local_Variable_1 : T1; Local_Variable_2 : T2; Local_Variable_3 : T3; ... end record; procedure Finalize (X: in out P_State_Type); end Frame_Finalization; package body Frame_Finalization is procedure Finalize (X: in out P_State_Type) is begin ... -- references to components of X end Finalize; end Frame_Finalization; procedure P is P_State : P_State_Type; begin ... -- statements of P, manipulating -- P_State.Local_Variable_1, -- P_State.Local_Variable_2, -- P_State.Local_Variable_3, ... end P; end P_Wrapper; The feature we considered during the 9X design, by the way, was simple, succinct, and intuitive: Everywhere Ada allows begin ... exception ... end we would have allowed begin ... exception ... at end < sequence of frame finalization statements > end The semantics would have been the same as the try { ... } catch { ... } finally { ... } construct in Java or TRY TRY ... EXCEPT ... END FINALLY ... END in Modula-3: The frame-finalization statements get executed both after normal exit from a frame and after execution of an exception handler for the frame. -- Norman H. Cohen mailto:ncohen@watson.ibm.com http://www.research.ibm.com/people/n/ncohen