17.2.11 Generalized Finalization

The Finalizable aspect can be applied to any record type, tagged or not, to specify that it provides the same level of control on the operations of initialization, finalization, and assignment of objects as the controlled types (see RM 7.6(2) for a high-level overview). The only restriction is that the record type must be a root type, in other words not a derived type.

The aspect additionally makes it possible to specify relaxed semantics for the finalization operations by means of the Relaxed_Finalization setting. Here is the archetypal example:

type T is record
  ...
end record
  with Finalizable => (Initialize           => Initialize,
                       Adjust               => Adjust,
                       Finalize             => Finalize,
                       Relaxed_Finalization => True);

procedure Adjust     (Obj : in out T);
procedure Finalize   (Obj : in out T);
procedure Initialize (Obj : in out T);

The three procedures have the same profile, with a single in out parameter, and also have the same dynamic semantics as for controlled types:

However, when Relaxed_Finalization is either True or not explicitly specified, the following differences are implemented relative to the semantics of controlled types:

Simple example of ref-counted type:

type T is record
   Value     : Integer;
   Ref_Count : Natural := 0;
end record;

procedure Inc_Ref (X : in out T);
procedure Dec_Ref (X : in out T);

type T_Access is access all T;

type T_Ref is record
   Value : T_Access;
end record
   with Finalizable => (Adjust   => Adjust,
                        Finalize => Finalize);

procedure Adjust (Ref : in out T_Ref) is
begin
   Inc_Ref (Ref.Value);
end Adjust;

procedure Finalize (Ref : in out T_Ref) is
begin
   Def_Ref (Ref.Value);
end Finalize;

Simple file handle that ensures resources are properly released:

package P is
   type File (<>) is limited private;

   function Open (Path : String) return File;

   procedure Close (F : in out File);

private
   type File is limited record
      Handle : ...;
   end record
      with Finalizable (Finalize => Close);
end P;