adafinalize

Best practice for implementing in Ada (2005 or 2012) an equivalent of the java finalize block


Java has the finalize block which allows to execute some statements after a block is left (executed even if an exception is raised). Example:

try {
  ...
} catch (Exception e) {
  ...
} finally {
  ... // any code here
}

Ada has the controlled objects which allows to implement a Finalize operation but there is no finalize block equivalent as in java. This is useful for logging, closing files, transactions and so on (without having to create a specific tagged type for each possible block).

  1. How would you implement such finalize block in Ada 2005 (while keeping the code readable)?
  2. Are there plans in Ada 2012 to allow executing any finalization code easily?

Solution

  • I believe this code will do what you ask; it successfully prints out 42 with the present raise or with return. It's an implementation of T.E.D's suggestion.

    Tested with GCC 4.5.0 on Mac OS X, Darwin 10.6.0.

    with Ada.Finalization;
    package Finally is
    
       --  Calls Callee on deletion.
       type Caller (Callee : not null access procedure)
          is new Ada.Finalization.Limited_Controlled with private;
    
    private
    
       type Caller (Callee : not null access procedure)
          is new Ada.Finalization.Limited_Controlled with null record;
    
       procedure Finalize (Object : in out Caller);
    
    end Finally;
    
    
    package body Finally is
    
       procedure Finalize (Object : in out Caller)
       is
       begin
          Object.Callee.all;
       end Finalize;
    
    end Finally;
    
    
    with Ada.Text_IO; use Ada.Text_IO;
    with Finally;
    procedure Finally_Demo is
    begin
    
       declare
    
          X : Integer := 21;
    
          --  The cleanup procedure, to be executed when this block is left
          procedure F
          is
          begin
             Put_Line ("X is " & Integer'Image (X));
          end F;
    
          --  The controlled object, whose deletion will execute F
          F_Caller : Finally.Caller (F'Access);
    
       begin
    
          X := 42;
    
          raise Constraint_Error;
    
       end;
    
    end Finally_Demo;