------------------------------------------------------------------------------ -- -- -- GNAT COMPILER COMPONENTS -- -- -- -- S Y S T E M . F I N A L I Z A T I O N _ P R I M I T I V E S -- -- -- -- S p e c -- -- -- -- Copyright (C) 2023-2024, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- -- ware Foundation; either version 3, or (at your option) any later ver- -- -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- -- or FITNESS FOR A PARTICULAR PURPOSE. -- -- -- -- As a special exception under Section 7 of GPL version 3, you are granted -- -- additional permissions described in the GCC Runtime Library Exception, -- -- version 3.1, as published by the Free Software Foundation. -- -- -- -- You should have received a copy of the GNU General Public License and -- -- a copy of the GCC Runtime Library Exception along with this program; -- -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- -- . -- -- -- -- GNAT was originally developed by the GNAT team at New York University. -- -- Extensive contributions were provided by Ada Core Technologies Inc. -- -- -- ------------------------------------------------------------------------------ with Ada.Finalization; with System.OS_Locks; with System.Storage_Elements; -- This package encapsulates the types and operations used by the compiler -- to support finalization of objects of Ada controlled types (types derived -- from types Controlled and Limited_Controlled). package System.Finalization_Primitives with Preelaborate is use type System.Storage_Elements.Storage_Offset; type Finalize_Address_Ptr is access procedure (Obj : System.Address); -- Values of this type denote finalization procedures associated with -- objects that have controlled parts. For convenience, such objects -- are simply referred to as controlled objects in the remainder of -- this package. type Master_Node is private; -- Each controlled object associated with a finalization master has an -- associated master node created by the compiler. type Master_Node_Ptr is access all Master_Node; for Master_Node_Ptr'Storage_Size use 0; -- A reference to a master node. Since this type may not be used to -- allocate objects, its storage size is zero. -------------------------------------------------------------------------- -- Types and operations of finalization masters: A finalization master -- is used to manage a set of controlled objects declared at the library -- level of the program or associated with the declarative part of a -- subprogram or other closed scopes (block statements, for example). type Finalization_Master (Exceptions_OK : Boolean; Extra_Info : Boolean; Library_Level : Boolean) is limited private; -- Objects of this type encapsulate an ordered list of zero or more master -- nodes, each of which is associated with a controlled object. procedure Attach_Object_To_Master (Object_Address : System.Address; Finalize_Address : not null Finalize_Address_Ptr; Node : not null Master_Node_Ptr; Master : in out Finalization_Master); -- Associates a controlled object and its master node with a given master. -- Finalize_Address denotes the operation to be called to finalize the -- object (which could be a user-declared Finalize procedure or a procedure -- generated by the compiler). An object can be associated with at most one -- finalization master. procedure Attach_Object_To_Node (Object_Address : System.Address; Finalize_Address : not null Finalize_Address_Ptr; Node : in out Master_Node); -- Associates a controlled object with its master node only. This is used -- when there is a single object to be finalized in the context, as well as -- for objects that need special processing (return object in an extended -- return statement or transient objects). procedure Chain_Node_To_Master (Node : not null Master_Node_Ptr; Master : in out Finalization_Master); -- Chain a master node to the given master. This is used to chain the node -- to the master of the enclosing scope for the objects that need special -- processing mentioned for Attach_Object_To_Node. procedure Finalize_Master (Master : in out Finalization_Master); -- Finalizes each of the controlled objects associated with Master, in the -- reverse of the order in which they were attached. Calls to the procedure -- with a Master that has already been finalized have no effects. procedure Finalize_Object (Node : in out Master_Node); -- Finalizes the controlled object attached to Node. Calls to the procedure -- with a Node that has already been finalized have no effects. procedure Suppress_Object_Finalize_At_End (Node : in out Master_Node); -- Changes the state of Node to effectively suppress a call to Node's -- associated object's Finalize procedure. This is called at the end -- of an extended return statement of a function whose result type -- needs finalization, to ensure that the function's return object is -- not finalized within the function in the case the return statement -- is completed normally (it will still be finalized if an exception -- is raised before the normal completion of the return statement). -------------------------------------------------------------------------- -- Types and operations of finalization collections: A finalization -- collection is used to manage a set of controlled objects associated -- with an access type. Such collections are always associated with a -- finalization master, either at the library-level or within a subprogram, -- depending on where the access type is declared, and the collection -- object itself is managed via a Master_Node attached to its finalization -- master. type Finalization_Collection is new Ada.Finalization.Limited_Controlled with private; -- Objects of this type encapsulate a set of zero or more controlled -- objects associated with an access type. The compiler ensures that -- each finalization collection is in turn associated with a finalization -- master. type Finalization_Collection_Ptr is access all Finalization_Collection; for Finalization_Collection_Ptr'Storage_Size use 0; -- A reference to a collection. Since this type may not be used to -- allocate objects, its storage size is zero. overriding procedure Initialize (Collection : in out Finalization_Collection); -- Initializes the dummy head of a collection overriding procedure Finalize (Collection : in out Finalization_Collection); -- Finalizes each object that has been associated with a finalization -- collection, in some arbitrary order. Calls to this procedure with -- a collection that has already been finalized have no effect. procedure Attach_Object_To_Collection (Object_Address : System.Address; Finalize_Address : not null Finalize_Address_Ptr; Collection : in out Finalization_Collection); -- Associates a controlled object allocated for some access type with a -- given finalization collection. Finalize_Address denotes the operation -- to be called to finalize the object (which could be a user-declared -- Finalize procedure or a procedure generated by the compiler). An object -- can be associated with at most one finalization collection. procedure Detach_Object_From_Collection (Object_Address : System.Address); -- Removes a controlled object from its associated finalization collection. -- Calls to the procedure with an object that has already been detached -- have no effects. function Header_Alignment return System.Storage_Elements.Storage_Count; -- Return the alignment of the header to be placed immediately in front of -- a controlled object allocated for some access type, in storage units. function Header_Size return System.Storage_Elements.Storage_Count; -- Return the size of the header to be placed immediately in front of a -- controlled object allocated for some access type, in storage units. private -- Since RTSfind cannot contain names of the form RE_"+", the following -- routine serves as a wrapper around System.Storage_Elements."+". function Add_Offset_To_Address (Addr : System.Address; Offset : System.Storage_Elements.Storage_Offset) return System.Address; -- Finalization masters: -- Master node type structure. Finalize_Address comes first because it is -- an access-to-subprogram and, therefore, might be twice as large and as -- aligned as an access-to-object on some platforms. type Master_Node is record Finalize_Address : Finalize_Address_Ptr := null; Object_Address : System.Address := System.Null_Address; Next : Master_Node_Ptr := null; end record; -- Finalization master type structure. A unique master is associated -- with each scope containing controlled objects. type Finalization_Master (Exceptions_OK : Boolean; Extra_Info : Boolean; Library_Level : Boolean) is limited record Head : Master_Node_Ptr := null; end record; -- These operations need to be performed in line for maximum performance pragma Inline (Attach_Object_To_Master); pragma Inline (Attach_Object_To_Node); pragma Inline (Chain_Node_To_Master); pragma Inline (Finalize_Object); pragma Inline (Suppress_Object_Finalize_At_End); -- Finalization collections: type Collection_Node; -- Each controlled object associated with a finalization collection has -- an associated object of this type. type Collection_Node_Ptr is access all Collection_Node; for Collection_Node_Ptr'Storage_Size use 0; pragma No_Strict_Aliasing (Collection_Node_Ptr); -- A reference to a collection node. Since this type may not be used to -- allocate objects, its storage size is zero. -- Collection node type structure. Finalize_Address comes first because it -- is an access-to-subprogram and, therefore, might be twice as large and -- as aligned as an access-to-object on some platforms. type Collection_Node is record Finalize_Address : Finalize_Address_Ptr := null; -- A pointer to the Finalize_Address procedure of the object Enclosing_Collection : Finalization_Collection_Ptr := null; -- A pointer to the collection to which the node is attached Prev : Collection_Node_Ptr := null; Next : Collection_Node_Ptr := null; -- Collection nodes are managed as a circular doubly-linked list end record; function Header_Alignment return System.Storage_Elements.Storage_Count is (Collection_Node'Alignment); function Header_Size return System.Storage_Elements.Storage_Count is (Collection_Node'Object_Size / Storage_Unit); -- Finalization collection type structure type Finalization_Collection is new Ada.Finalization.Limited_Controlled with record Head : aliased Collection_Node; -- The head of the circular doubly-linked list of collection nodes Lock : aliased System.OS_Locks.RTS_Lock; -- A lock to synchronize concurrent accesses to the collection Finalization_Started : Boolean; -- A flag used to detect allocations which occur during the finalization -- of a collection. The allocations must raise Program_Error. This may -- arise in a multitask environment. end record; -- This operation is very simple and thus can be performed in line pragma Inline (Initialize); end System.Finalization_Primitives;