comp.lang.ada
 help / color / mirror / Atom feed
* Deallocation & Tagged Types
@ 2003-10-18 20:53 chris
  2003-10-19 15:38 ` Robert I. Eachus
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: chris @ 2003-10-18 20:53 UTC (permalink / raw)


Hi,

I've got a situation involving deallocating an object from a proxy and 
am a bit stuck...  Namely how to deallocate an object belonging to a 
particular class but not knowing the specific type.

The example is not from the code, it just highlights the problem...


-- a vehicles package
--
package Vehicles is

    type Vehicle is abstract tagged null record;
    type Vehicle_Access is access all Vehicle'class;

    procedure Destroy (V : in out Vehicle) is abstract;

end Vehicles;

-- proxies for vehicles
--
package Vehicle_Proxy is

    type Proxy is new Vehicle with private;

    procedure Destroy (V : in out Proxy);

private
    type Proxy is new Vehicle with record
       Actual : Vehicle_Access;
    end record;

end Vehicle_Proxy;

package body Vehicle_Proxy is

    procedure Destroy (V : in out Proxy) is
    begin
       Destroy (V.Actual.all);

       -- now what???
    end Destroy;

end Vehicle_Proxy;



If V.Actual isn't properly disposed of, the proxy will leak.  What's the 
best way to handle this?  One way I can think of is to do something like 
this...

type Vehicle_Deallocator
    is access procedure (V : in out Vehicle_Access);

and revise type Proxy to the following,

    type Proxy is new Vehicle with record
       Actual  : Vehicle_Access;
       Dealloc : Vehicle_Deallocator;
    end record;

and Destroy to

    procedure Destroy (V : in out Proxy) is
    begin
       Destroy (V.Actual.all);
       V.Dealloc (V.Actual);
       V.Actual := null;
    end Destroy;


Is there another way that I'm missing or is this how people do this in 
their code?  I also came up against this when making a container type (a 
container for rasters in the real code).  Namely if you stuff 
Raster_Access into a container (an Image) and destroy the Image 
container, you need to deallocate the rasters.  That means you need to 
have a deallocator capable of handling the types derived from Raster. 
If you miss one, the code breaks.

The alternative is to deallocate each raster outside of the image 
container, but you still need someway of handling each subclass of raster.



Cheers,
Chris




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Deallocation & Tagged Types
  2003-10-18 20:53 Deallocation & Tagged Types chris
@ 2003-10-19 15:38 ` Robert I. Eachus
  2003-10-19 16:53   ` chris
  2003-10-19 16:10 ` Dmitry A. Kazakov
  2003-10-26  8:11 ` Patrice Freydiere
  2 siblings, 1 reply; 9+ messages in thread
From: Robert I. Eachus @ 2003-10-19 15:38 UTC (permalink / raw)


chris wrote:

> Is there another way that I'm missing or is this how people do this in 
> their code?

This is what Controlled types were added to the language for, why aren't 
you using them?  In your example, if Vehicle is a controlled type, you 
don't have a problem.  If Vehicle has no required finalization, it 
doesn't need to be derived from Controlled (or Limited_Controlled) but 
again, as the programmer of an abstraction that uses Vehicle, you don't 
have to worry about it.

Incidently this is as I see it the biggest problem that programmers 
moving from C++ or other OO languages to Ada have.  Ada programmers are 
used to trusting the developers of each abstraction to manage storage, 
initialization, and a lot of other things correctly.  Programmers new to 
Ada spend a lot of time worrying about these things that Ada programmers 
take for granted.  I can say, teach, describe, whatever this attitude, 
but it takes years for the worry to go away.

(Note:  I understand that if someone programs an abstraction 
incorrectly, that is a problem.  But it is also a bug in the ADT that 
needs to be fixed there.  Code that includes workarounds for bugs in the 
ADTs used is twice wrong.  Once because the original type should be 
corrected, and the second time because fixing the base abstraction is 
now going to create a follow-on bug.)
-- 
                                          Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the 
goal of Art. It remains to work these concepts into a practical, 
down-to-earth context, and for this there is nothing more practical or 
down-to-earth than what I have been talking about all along...the repair 
of an old motorcycle."  -- from Zen and the Art of Motorcycle 
Maintenance by Robert Pirsig




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Deallocation & Tagged Types
  2003-10-18 20:53 Deallocation & Tagged Types chris
  2003-10-19 15:38 ` Robert I. Eachus
@ 2003-10-19 16:10 ` Dmitry A. Kazakov
  2003-10-19 16:50   ` chris
  2003-10-26  8:11 ` Patrice Freydiere
  2 siblings, 1 reply; 9+ messages in thread
From: Dmitry A. Kazakov @ 2003-10-19 16:10 UTC (permalink / raw)


chris wrote:

> I've got a situation involving deallocating an object from a proxy and
> am a bit stuck...  Namely how to deallocate an object belonging to a
> particular class but not knowing the specific type.
> The example is not from the code, it just highlights the problem...
> 
> -- a vehicles package
> --
> package Vehicles is
> 
>     type Vehicle is abstract tagged null record;
>     type Vehicle_Access is access all Vehicle'class;
> 
>     procedure Destroy (V : in out Vehicle) is abstract;
> 
> end Vehicles;
> 
> -- proxies for vehicles
> --
> package Vehicle_Proxy is
> 
>     type Proxy is new Vehicle with private;
> 
>     procedure Destroy (V : in out Proxy);
> 
> private
>     type Proxy is new Vehicle with record
>        Actual : Vehicle_Access;
>     end record;
> 
> end Vehicle_Proxy;
> 
> package body Vehicle_Proxy is
> 
>     procedure Destroy (V : in out Proxy) is
>     begin
>        Destroy (V.Actual.all);
> 
>        -- now what???

Same as with any other access type (except an access to subprogram, mind you
(:-)):

function Free is
   new Ada.Unchecked_Deallocation (Vehicle'Class, Vehicle_Access);

Free (V.Actual);
   -- Kills V.Actual and sets V.Actual to null,
   -- or does nothing if V.Actual is already null

Note that Free releases a _class-wide_ object. So it first dispatches to
whatever language-defined finalization is required (for a controlled type
it is Finalize) then it deallocates the memory.

BTW, it is better to make Vehicle and Proxy controlled and name Destroy
"Finalize", which will be then called implicitly, and note always the right
one. It need not to be abstract because the type Vehicle is already
abstract, so no harm can be done anyway.

>     end Destroy;
> 
> end Vehicle_Proxy;
> 
> If V.Actual isn't properly disposed of, the proxy will leak.  What's the
> best way to handle this?  One way I can think of is to do something like
> this...
> [...]

This is what tagged types are for. And note that Ada is a very consistent
and consequent language. If it allows class-wide objects, it also allows
them destroyed in a reasonable way.

> Is there another way that I'm missing or is this how people do this in
> their code?

For example:

http://www.dmitry-kazakov.de/ada/components.htm

> I also came up against this when making a container type (a
> container for rasters in the real code).  Namely if you stuff
> Raster_Access into a container (an Image) and destroy the Image
> container, you need to deallocate the rasters.  That means you need to
> have a deallocator capable of handling the types derived from Raster.
> If you miss one, the code breaks.

See above.

-- 
Regards,
Dmitry A. Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Deallocation & Tagged Types
  2003-10-19 16:10 ` Dmitry A. Kazakov
@ 2003-10-19 16:50   ` chris
  2003-10-20  1:13     ` Robert I. Eachus
  0 siblings, 1 reply; 9+ messages in thread
From: chris @ 2003-10-19 16:50 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> 
> Same as with any other access type (except an access to subprogram, mind you
> (:-)):
> 
> function Free is
>    new Ada.Unchecked_Deallocation (Vehicle'Class, Vehicle_Access);
> 
> Free (V.Actual);
>    -- Kills V.Actual and sets V.Actual to null,
>    -- or does nothing if V.Actual is already null

Interesting... I didn't know you could do that.  I had tried just 
Vehicle not Vehicle'Class but that was obviously wrong.  I must remember 
that you can instantiate generics like that.


> Note that Free releases a _class-wide_ object. So it first dispatches to
> whatever language-defined finalization is required (for a controlled type
> it is Finalize) then it deallocates the memory.
> 
> BTW, it is better to make Vehicle and Proxy controlled and name Destroy
> "Finalize", which will be then called implicitly, and note always the right
> one. It need not to be abstract because the type Vehicle is already
> abstract, so no harm can be done anyway.

In the code they are Controlled and the Finalization routine does tidy 
up, but it too got stuck at getting rid of V.Actual access variable. 
Now it can go away too.  What is the benefit of making "destroy", 
"finalize"?


Thanks,
Chris




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Deallocation & Tagged Types
  2003-10-19 15:38 ` Robert I. Eachus
@ 2003-10-19 16:53   ` chris
  2003-10-20  1:08     ` Robert I. Eachus
  0 siblings, 1 reply; 9+ messages in thread
From: chris @ 2003-10-19 16:53 UTC (permalink / raw)


Robert I. Eachus wrote:
> 
> This is what Controlled types were added to the language for, why aren't 
> you using them?  In your example, if Vehicle is a controlled type, you 
> don't have a problem.  If Vehicle has no required finalization, it 
> doesn't need to be derived from Controlled (or Limited_Controlled) but 
> again, as the programmer of an abstraction that uses Vehicle, you don't 
> have to worry about it.

In the real code, the types *are* controlled.  The problem was how to 
get rid of X when X is of type access to Vehicle'Class, not how to tidy 
up X after use when it is a Vehicle.  I wasn't clear sorry.

I tried instantiating Unchecked_Deallocation on Vehicle and not 
Vehicle'Class not knowing you could do that.

> (Note:  I understand that if someone programs an abstraction 
> incorrectly, that is a problem.  But it is also a bug in the ADT that 
> needs to be fixed there.  Code that includes workarounds for bugs in the 
> ADTs used is twice wrong.  Once because the original type should be 
> corrected, and the second time because fixing the base abstraction is 
> now going to create a follow-on bug.)

Yes the ADT abstraction was broken, but only after trying to get around 
the problem of deallocating the access component in the record.  The 
ugliness is (IMO) gone now.


Chris




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Deallocation & Tagged Types
  2003-10-19 16:53   ` chris
@ 2003-10-20  1:08     ` Robert I. Eachus
  0 siblings, 0 replies; 9+ messages in thread
From: Robert I. Eachus @ 2003-10-20  1:08 UTC (permalink / raw)


chris wrote:

 > I tried instantiating Unchecked_Deallocation on Vehicle and not
 > Vehicle'Class not knowing you could do that.

Sigh, I should have tried harder to get that notation fixed in Ada 83. 
Most of the time the Object name in an instantiation of 
Unchecked_Deallocation is a dummy parameter.

Yes, there are cases where the size of the object being deallocated 
cannot be determined from the access type name, and the subtype of the 
Object type can be used by the compiler.  But that only argues that 
there should be two versions of Unchecked_Deallocation, and the compiler 
should reject the one parameter version at compile time if it does need 
to use the designated subtype information.  But that would IMHO be 
better than allowing users to instantiate with the "wrong" constrained 
subtype thinking it doesn't matter.

Requiring the user to provide the "right" subtype when it doesn't 
matter--except that the compiler can reject a wrong value--is one of 
those "little tests" that Tucker used to talk about.

 > Yes the ADT abstraction was broken, but only after trying to get
 > around the problem of deallocating the access component in the
 > record.  The ugliness is (IMO) gone now.

It sounds like you are still doing more than you really have to.  But I
don't know understand your full design well enough to understand whether
  the explicit allocation and deallocation are necessary.

But I assume that your "Proxy" notation indicates that you do need to
use a pointer to the object rather than copying the object.


-- 
                                        Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the
goal of Art. It remains to work these concepts into a practical,
down-to-earth context, and for this there is nothing more practical or
down-to-earth than what I have been talking about all along...the repair
of an old motorcycle."  -- from Zen and the Art of Motorcycle
Maintenance by Robert Pirsig




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Deallocation & Tagged Types
  2003-10-19 16:50   ` chris
@ 2003-10-20  1:13     ` Robert I. Eachus
  2003-10-20  1:43       ` Hyman Rosen
  0 siblings, 1 reply; 9+ messages in thread
From: Robert I. Eachus @ 2003-10-20  1:13 UTC (permalink / raw)


chris wrote:

> In the code they are Controlled and the Finalization routine does tidy 
> up, but it too got stuck at getting rid of V.Actual access variable. Now 
> it can go away too.  What is the benefit of making "destroy", "finalize"?

It will be called automagically when the container object goes away, if 
it is also controlled. You don't need to explicitly call it.  This is 
why garbage collectors for Ada are so useless.  If the ADT is created 
right, there is no garbage to collect later, and never any garbage for 
the user of the type to worry about.

-- 
                                                     Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the 
goal of Art. It remains to work these concepts into a practical, 
down-to-earth context, and for this there is nothing more practical or 
down-to-earth than what I have been talking about all along...the repair 
of an old motorcycle."  -- from Zen and the Art of Motorcycle 
Maintenance by Robert Pirsig




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Deallocation & Tagged Types
  2003-10-20  1:13     ` Robert I. Eachus
@ 2003-10-20  1:43       ` Hyman Rosen
  0 siblings, 0 replies; 9+ messages in thread
From: Hyman Rosen @ 2003-10-20  1:43 UTC (permalink / raw)


Robert I. Eachus wrote:
 > This is why garbage collectors for Ada are so useless.

Another reason is Ada's ability to have parameters, return
values, and variables of unconstrained types. This allows
stack objects to be used in places where other languages,
such as C++, require dynamic allocation. Less "garbage"
created means less garbage to collect.




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Deallocation & Tagged Types
  2003-10-18 20:53 Deallocation & Tagged Types chris
  2003-10-19 15:38 ` Robert I. Eachus
  2003-10-19 16:10 ` Dmitry A. Kazakov
@ 2003-10-26  8:11 ` Patrice Freydiere
  2 siblings, 0 replies; 9+ messages in thread
From: Patrice Freydiere @ 2003-10-26  8:11 UTC (permalink / raw)




i had the same problem , i solve the issue using the "access" keyword in
the destroying procedure.

you can use access keyword to dispatch class wide type on the
corresponding object.

use this prototype on the class base definition :

procedure Destroy(V: access Vehicule) is abstract


and for each sub objects

procedure Destroy(P : access Proxy) is
begin
   ... -- Proxy specific desallocation operations
end;

hope this help

Patrice



On Sat, 18 Oct 2003 21:53:02 +0100, chris wrote:

> Hi,
> 
> I've got a situation involving deallocating an object from a proxy and 
> am a bit stuck...  Namely how to deallocate an object belonging to a 
> particular class but not knowing the specific type.
> 
> The example is not from the code, it just highlights the problem...
> 
> 
> -- a vehicles package
> --
> package Vehicles is
> 
>     type Vehicle is abstract tagged null record;
>     type Vehicle_Access is access all Vehicle'class;
> 
>     procedure Destroy (V : in out Vehicle) is abstract;
> 
> end Vehicles;
> 
> -- proxies for vehicles
> --
> package Vehicle_Proxy is
> 
>     type Proxy is new Vehicle with private;
> 
>     procedure Destroy (V : in out Proxy);
> 
> private
>     type Proxy is new Vehicle with record
>        Actual : Vehicle_Access;
>     end record;
> 
> end Vehicle_Proxy;
> 
> package body Vehicle_Proxy is
> 
>     procedure Destroy (V : in out Proxy) is
>     begin
>        Destroy (V.Actual.all);
> 
>        -- now what???
>     end Destroy;
> 
> end Vehicle_Proxy;
> 
> 
> 
> If V.Actual isn't properly disposed of, the proxy will leak.  What's the 
> best way to handle this?  One way I can think of is to do something like 
> this...
> 
> type Vehicle_Deallocator
>     is access procedure (V : in out Vehicle_Access);
> 
> and revise type Proxy to the following,
> 
>     type Proxy is new Vehicle with record
>        Actual  : Vehicle_Access;
>        Dealloc : Vehicle_Deallocator;
>     end record;
> 
> and Destroy to
> 
>     procedure Destroy (V : in out Proxy) is
>     begin
>        Destroy (V.Actual.all);
>        V.Dealloc (V.Actual);
>        V.Actual := null;
>     end Destroy;
> 
> 
> Is there another way that I'm missing or is this how people do this in 
> their code?  I also came up against this when making a container type (a 
> container for rasters in the real code).  Namely if you stuff 
> Raster_Access into a container (an Image) and destroy the Image 
> container, you need to deallocate the rasters.  That means you need to 
> have a deallocator capable of handling the types derived from Raster. 
> If you miss one, the code breaks.
> 
> The alternative is to deallocate each raster outside of the image 
> container, but you still need someway of handling each subclass of raster.
> 
> 
> 
> Cheers,
> Chris




^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2003-10-26  8:11 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-18 20:53 Deallocation & Tagged Types chris
2003-10-19 15:38 ` Robert I. Eachus
2003-10-19 16:53   ` chris
2003-10-20  1:08     ` Robert I. Eachus
2003-10-19 16:10 ` Dmitry A. Kazakov
2003-10-19 16:50   ` chris
2003-10-20  1:13     ` Robert I. Eachus
2003-10-20  1:43       ` Hyman Rosen
2003-10-26  8:11 ` Patrice Freydiere

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