comp.lang.ada
 help / color / mirror / Atom feed
From: david.c.hoos.sr@ada95.com
Subject: Re: Destructor question
Date: 1998/12/06
Date: 1998-12-06T00:00:00+00:00	[thread overview]
Message-ID: <74d0i5$itj$1@nnrp1.dejanews.com> (raw)
In-Reply-To: 3665B85D.A2663591@nowhere.com

In article <3665B85D.A2663591@nowhere.com>,
  Rusnak <bogus@nowhere.com> wrote:
> How are destrcutor methords properly implemented in Ada on tagged
> records?  I have the following setup:
<snip>

Here is my solution to the problem, based on Robert Eachus's post to this
thread.

I do, however, find some points of Robert's posting at variance with what I
was able to make work, viz.:

    1.  Robert said "Next, you need, and this need not be visible, to have a
        two parameter version that is dispatching on Object"  I do not see how
        this can be made invisible, since it needs to be a primitive operation
        of the type.  Perhaps someone can enlightne me on this.

    2.  Robert said "Note that the parameter "The_Object" is never used, it is
        just there to get the dispatching."  This would be true if it were not
        for your requirement that you be able to deallocate internal
        dynamically-allocated components.

At any rate, here is a sample program which is a complete and working
implementation of Robert's ideas.  I hope it helps.  The exercise certainly
clarified the solution for me.

David C. Hoos, Sr.

with Ada.Tags;
with Ada.Text_Io;
with Ada.Unchecked_Deallocation;
procedure Test_Rusnak is

   package Rusnak is

      type Instance is abstract tagged null record;

      type Object_Class is access all Instance'Class;

      -- This procedure can never be called, since no instance of an
      -- abstract type can exist, but it must exist, otherwise the
      -- single-parameter Deallocate will not compile.
      procedure Deallocate
        (The_Access : in out Object_Class;
         The_Object : in out Instance);

      -- This is the class-wide deallocation procedure which is called to
      -- deallocate any objet of a type derived from Instance.  It makes a
      -- dispatching call to the appropriate two-parameter Deallocate
      -- procedure which must be a primitive operation for all types derived
      -- from Instance.
      procedure Deallocate (The_Access : in out Object_Class);

      -- This is the type of a component of type Derived.
      type String_Access is access all String;

      -- This type is an example of a concrete type derived from Instance
      -- which has internal dynamically-allocated objects which need to be
      -- deallocated when an object of the type is deallocated.
      type Derived is new Instance with record
         Data_Access: String_Access;
      end record;

      -- This is the two-parameter Deallocate procedure, a primitive operation
      -- of type Derived.  It must be declared at this point -- i.e. before
      -- Derived is frozen.
      procedure Deallocate
        (The_Access : in out Object_Class;
         The_Object : in out Derived);

   end Rusnak;

   package body Rusnak is

      procedure Deallocate
        (The_Access : in out Object_Class;
         The_Object : in out instance) is
      begin
         null;
      end Deallocate;

      -- This type serves only to provide the required parameter type for an
      -- instantiation of Ada.Unchecked_Deallocation.  It must be decalred
      -- here instead of inside the Deallocate procedure, in order that it
      -- have the same access level as the type which it accesses.
      type Derived_Class is access all Derived;

  -- This procedure is declared outside the Deallocate procedure from which 
-- it is called, only because it is for a type which would likely be used  --
for components of more than one type derived from Instance.  procedure Free
is new Ada.Unchecked_Deallocation  (Object => string,  Name =>
String_access);

      procedure Deallocate
        (The_Access : in out Object_Class;
         The_Object : in out Derived) is
         procedure Free is new Ada.Unchecked_Deallocation
           (Object => derived,
            Name => derived_Class);
      begin
         Ada.Text_Io.Put_Line ("Deallocating ""derived"" object");
         Free (The_Object.Data_Access);
         Free (Derived_Class (The_Access));
      end Deallocate;

      procedure Deallocate (The_Access : in out Object_Class) is
      begin
         Ada.Text_Io.Put_Line
           ("Dispatching to deallocator for concrete type """ &
            Ada.Tags.External_Tag (The_Access.all'Tag) & """.");
         Deallocate (The_Access => The_Access, The_Object => The_Access.all);
      end Deallocate;

   end Rusnak;

   The_Derived_Object_access : Rusnak.Object_class :=
    new Rusnak.Derived'(Data_Access => new String'("this is the data"));

begin

   Ada.Text_Io.Put_Line
     (Rusnak.Derived (The_Derived_Object_Access.all).Data_Access.all);
   Rusnak.Deallocate (The_Derived_Object_Access);
   Ada.Text_Io.Put_Line("The next statement will raise Constraint_Error");
   Ada.Text_Io.Put_Line
     (Rusnak.Derived (The_Derived_Object_Access.all).Data_Access.all);

end Test_Rusnak;



-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




  parent reply	other threads:[~1998-12-06  0:00 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1998-12-02  0:00 Destructor question Rusnak
1998-12-03  0:00 ` Jeff Carter
1998-12-03  0:00   ` Rusnak
1998-12-04  0:00     ` Robert I. Eachus
1998-12-06  0:00       ` Matthew Heaney
1998-12-08  0:00         ` Robert I. Eachus
1998-12-06  0:00     ` Matthew Heaney
1998-12-07  0:00     ` Jeff Carter
1998-12-06  0:00 ` david.c.hoos.sr [this message]
1998-12-06  0:00   ` Matthew Heaney
1998-12-08  0:00   ` Robert I. Eachus
1998-12-06  0:00 ` Matthew Heaney
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox