[comp.lang.ada] Destroy and Unchecked Deallocation

TUFFS1@alcoa.com (12/06/88)

Bill Wolfe writes (Info-Ada Digest V88 #244, 23 Nov 1988):
>...
>> 
>> This needs clarification; what does a DESTROY procedure do that
>> UNCHECKED_DEALLOCATION doesn't?
>
>      Consider an ADT which contains pointers to substructures.
>      A user declares an access type pointing to an instance of your
>      ADT, and uses UNCHECKED_DEALLOCATION to destroy that instance
>      after finishing with it.  UNCHECKED_DEALLOCATION will not 
>      recursively chase down and free up what might constitute 
>      over 99% of the space occupied by the ADT.   Similarly, if your
>      ADT uses another ADT in its implememtation, your DESTROY procedure
>      will include a call to the DESTROY procedure of the sub-ADT,
>      but UNCHECKED_DEALLOCATION will remain oblivious to the method
>      which must be used to properly destroy the sub-ADT.
>...

I believe the effect you want can be implemented within Ada as it stands.  
Following LRM 13.10 (2), define a new Deallocate generic, and have the 
user avoid direct reference to Unchecked_Deallocation:

generic
  type Object is limited private;
  type Name is access Object;
  with procedure Destroy(Y: in out Object) is <>;
procedure Deallocate(X: in out Name);

with Unchecked_Deallocation;
procedure Deallocate(X: in out Name) is
  procedure Clean_Up is new Unchecked_Deallocation(Object, Name);
begin
  Destroy(X.all);
  Clean_Up(X);
end Deallocate;


Simon Tuffs
Tuffs@Alcoa.com

billwolf@hubcap.clemson.edu (William Thomas Wolfe,2847,) (12/15/88)

From article <8812140455.AA16285@ajpo.sei.cmu.edu>, by TUFFS1@alcoa.com:
> generic
>   type Object is limited private;
>   type Name is access Object;
>   with procedure Destroy(Y: in out Object) is <>;
> procedure Deallocate(X: in out Name);
> 
> with Unchecked_Deallocation;
> procedure Deallocate(X: in out Name) is
>   procedure Clean_Up is new Unchecked_Deallocation(Object, Name);
> begin
>   Destroy(X.all);
>   Clean_Up(X);
> end Deallocate;

  Deallocate needs to be revised as follows:

     begin
        if (X /= null) then  
           Destroy (X.all);  --  avoiding a CONSTRAINT_ERROR here...
           Clean_Up (X);
        end if;
     end Deallocate;

  Also, it's probably safer to revise the spec of the ADT to read:

     type POINTER_TO_ADT is access ADT;

     procedure DESTROY (TARGETED_OBJECT : in out POINTER_TO_ADT);

        -- This procedure, unlike UNCHECKED_DEALLOCATION, will
        --   properly destroy the ADT being pointed to...

  and then hide the instantiation in the package body.  This will 
  reduce the length of the user's "with" list, and give the user 
  less opportunity to screw up the instantiation,