comp.lang.ada
 help / color / mirror / Atom feed
* access to controlled types
@ 1999-02-03  0:00 Terry J. Westley
  1999-02-04  0:00 ` Stephen Leake
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Terry J. Westley @ 1999-02-03  0:00 UTC (permalink / raw)


In a new version of TASH, I've implmented an interface
to Tcl objects (which are reference counted) with Ada
controlled types.  I've been very impressed with how
well this works in GNAT.

But, there are certain calls in the interface which
return an access to a class-wide type.  It's easy to
reference count these newly created objects, but since
the access type is not controlled, the reference counts
don't get decremented.  What's the solution?  Should I
declare another controlled type which *contains* an
access to the original controlled type?  Or, is there
a better solution?

--
Terry J. Westley, Principal Engineer
Veridian Engineering, Calspan Operations
twestley@buffalo.veridian.com   http://www.veridian.com/
-------------------------------------------------------
Author of TASH, an Ada binding to Tcl/Tk.
Visit the TASH web site at http://tash.calspan.com.
-------------------------------------------------------








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

* Re: access to controlled types
  1999-02-03  0:00 access to controlled types Terry J. Westley
  1999-02-04  0:00 ` Stephen Leake
@ 1999-02-04  0:00 ` news.oxy.com
  1999-02-05  0:00   ` Garb Coll + Heap Cmpctn (was:access to controlled types) Nick Roberts
  1999-03-01  0:00 ` access to controlled types Matthew Heaney
  2 siblings, 1 reply; 8+ messages in thread
From: news.oxy.com @ 1999-02-04  0:00 UTC (permalink / raw)



Terry J. Westley wrote in message
<918079635.219550@outpost1.roc.accglobal.net>...
>
>But, there are certain calls in the interface which
>return an access to a class-wide type.  It's easy to
>reference count these newly created objects, but since
>the access type is not controlled, the reference counts
>don't get decremented.  What's the solution?  Should I
>declare another controlled type which *contains* an
>access to the original controlled type?  Or, is there
>a better solution?


I think this is one of the best solutions. I did exactly the same some time
ago when  I was playing  with controlled types aiming at creating some type
of universal class-wide communication objects (controlled types)  that could
work in conjunction with access types to them and all that together should
perform automatic garbage collection.

The problem with the simple access types to the controlled types was that
they do not resolve the problem of deleting  controlled types when there is
no more references to the last ones. Controlled types are only deleted on
leaving their life scope. Object lifetime scope can be reduced by using
internal/local blocks but in many cases this is not an optimal solution.

To resolve that I created and tested small top-level package that performs
user defined garbage collection using controlled access type to the
controlled class-wide types. This package (just small experiment or
exercise) proved to be working fine and I an going to use it  later to
create hierarchy of controlled types with automatic garbage collection.

Just few days ago I remembered one of the questions that was asked somewhere
some time ago (I do not remember where). The problem was how to distinguish
statically created objects at compile time from the dynamically created
objects during run time.
This is very important in conjunction with controlled types as any attempt
to free up static object will raise run-time error. Only dynamically created
objects may be deleted.
 As I understand this issue is not addressed in the LRM (but may be I am
wrong and someone will correct me), so I invented some kind of solution to
resolve this issue an I am going to test it as well when I add that changes
in my package. If that solution (it is extremely simple)  would be used by
the compiler itself then life would be much more easier.

Another issue is that sometimes it is necessary to postpone deleting of the
object in order not to affect performance of your code. This  also can be
easily resolved by creating separate garbage collection process that
performs the delayed  deleting of your object. During finalization (if the
object should be deleted) you just pass reference to your controlled object
to that garbage collection process and that's it. That garbage collection
process can be any structure (list, tree e.t.c.) containing controlled
access type to class-wide controlled types and set of needed operations on
that structure to perform controlled finalization of the objects within that
structure.

I should mention that I am not a programmer. I am telecommunications
engineer so I am playing with Ada occasionally. Also I never read anything
about how garbage collection is implemented in any other system.
What I was describing was just  my own approach to that problem using Ada
facilities.
May be there is something  wrong in what I am doing. May be there exist
better solutions.

As a matter of fact  garbage collection issues have somewhat increased
significance now and maybe it is worth to discuss it in separate discussion
thread. I have some topics for that discussion

Regards,
Vladimir Olensky
(vladimir_olensky@yahoo.com)
(Vladimir_Olensky@oxy.com)
Telecommunication specialist,
Occidental C.I.S. Service, Inc. ( www.oxy.com )
Moscow,
Russia.




















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

* Re: access to controlled types
  1999-02-03  0:00 access to controlled types Terry J. Westley
@ 1999-02-04  0:00 ` Stephen Leake
  1999-02-05  0:00   ` Terry J. Westley
  1999-02-04  0:00 ` news.oxy.com
  1999-03-01  0:00 ` access to controlled types Matthew Heaney
  2 siblings, 1 reply; 8+ messages in thread
From: Stephen Leake @ 1999-02-04  0:00 UTC (permalink / raw)


"Terry J. Westley" <twestley@buffalo.veridian.com> writes:

> In a new version of TASH, I've implmented an interface
> to Tcl objects (which are reference counted) with Ada
> controlled types.  I've been very impressed with how
> well this works in GNAT.
> 
> But, there are certain calls in the interface which
> return an access to a class-wide type.  It's easy to
> reference count these newly created objects, but since
> the access type is not controlled, the reference counts
> don't get decremented.  What's the solution?  Should I
> declare another controlled type which *contains* an
> access to the original controlled type?  Or, is there
> a better solution?

Perhaps the functions that return a class-wide access type should
simply be removed. Do they serve a real purpose in the system? Is
there another (safer) way to satisfy that need? I guess the latter is
what you are suggesting. But often, a function that violates an
abstraction truly does not belong.

-- Stephe




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

* Re: Garb Coll + Heap Cmpctn (was:access to controlled types)
  1999-02-04  0:00 ` news.oxy.com
@ 1999-02-05  0:00   ` Nick Roberts
  0 siblings, 0 replies; 8+ messages in thread
From: Nick Roberts @ 1999-02-05  0:00 UTC (permalink / raw)


news.oxy.com wrote in message <79bjn8$5ao$1@remarQ.com>...
[...]
|As a matter of fact  garbage collection issues have somewhat increased
|significance now and maybe it is worth to discuss it in separate discussion
|thread. I have some topics for that discussion


By all means.
(See also: separate thread).

-------------------------------------------
Nick Roberts
-------------------------------------------








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

* Re: access to controlled types
  1999-02-04  0:00 ` Stephen Leake
@ 1999-02-05  0:00   ` Terry J. Westley
  1999-02-20  0:00     ` Matthew Heaney
  0 siblings, 1 reply; 8+ messages in thread
From: Terry J. Westley @ 1999-02-05  0:00 UTC (permalink / raw)


>"Terry J. Westley" <twestley@buffalo.veridian.com> writes:
>
>> In a new version of TASH, I've implmented an interface
>> to Tcl objects (which are reference counted) with Ada
>> controlled types.  I've been very impressed with how
>> well this works in GNAT.
>>
>> But, there are certain calls in the interface which
>> return an access to a class-wide type.  It's easy to
>> reference count these newly created objects, but since
>> the access type is not controlled, the reference counts
>> don't get decremented.  What's the solution?  Should I
>> declare another controlled type which *contains* an
>> access to the original controlled type?  Or, is there
>> a better solution?
>

Stephen Leake <Stephen.Leake@gsfc.nasa.gov> responds:
>Perhaps the functions that return a class-wide access type should
>simply be removed. Do they serve a real purpose in the system? Is
>there another (safer) way to satisfy that need? I guess the latter is
>what you are suggesting. But often, a function that violates an
>abstraction truly does not belong.

You have a good point.  I'll think about it a bit.  The specific
situation is that TASH supports Tcl lists which are heterogenous.

So, when you fetch an element out of the list, it could be an
integer, a float, a string, or another list.

Other functions that return an element of the list are Head and Tail.

--
Terry J. Westley, Principal Engineer
Veridian Engineering, Calspan Operations
twestley@buffalo.veridian.com   http://www.veridian.com/
-------------------------------------------------------
Author of TASH, an Ada binding to Tcl/Tk.
Visit the TASH web site at http://tash.calspan.com.
-------------------------------------------------------







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

* Re: access to controlled types
  1999-02-05  0:00   ` Terry J. Westley
@ 1999-02-20  0:00     ` Matthew Heaney
  1999-02-20  0:00       ` Matthew Heaney
  0 siblings, 1 reply; 8+ messages in thread
From: Matthew Heaney @ 1999-02-20  0:00 UTC (permalink / raw)


"Terry J. Westley" <twestley@buffalo.veridian.com> writes:

> You have a good point.  I'll think about it a bit.  The specific
> situation is that TASH supports Tcl lists which are heterogenous.
> 
> So, when you fetch an element out of the list, it could be an
> integer, a float, a string, or another list.


Can your list return a discriminated object? Something like the code
below.

I don't think you need to return a tagged type object here, because your
interest is in an object (the item in the list), not in operations of a
type.

The items in your list are heterogenous, but they are all not part of
the same type hierarchy: floats and integers and strings and lists are
all different classes of types.  That means you need a variant record,
not a tagged type.

To use this list, you'd do like this:

declare
  Item : constant List_Item := Get_Head (List);
begin
  case Get_Item_Kind (Item) is
    when Float_List_Item =>
        declare
          F : constant Float := Get_Float_Item (Item);
        begin
          <do something with F>
        end;

    when Integer_List_Item => 
        ...

end;



with Ada.Finalization;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

package Lists is

   type List_Type is private;

   type List_Item (<>) is private;

   function Get_Head
     (List : List_Type) return List_Item;

   -- other list ops here

   type List_Item_Kind is
      (Float_List_Item,
       Integer_List_Item,
       String_List_Item,
       List_List_Item);

   function Get_Item_Kind
     (Item : List_Item) return List_Item_Kind;

   function Get_Float_Item
     (Item : List_Item) return Float;

   -- gets for other kinds here

private

   type Node_Type;
   type Node_Access is access Node_Type;

   type List_Type is
     new Ada.Finalization.Controlled with record
        Head : Node_Access;
     end record;

   procedure Adjust (List : in out List_Type);

   procedure Finalize (List : in out List_Type);


   type List_Item
     (Kind : List_Item_Kind := List_Item_Kind'First) is
      record
         case Kind is
            when Float_List_Item =>
               F : Float;

            when Integer_List_Item =>
               I : Integer;

            when String_List_Item =>
               S : Unbounded_String;

            when List_List_Item =>
               L : List_Type;

         end case;
      end record;

end Lists;



package body Lists is

   type Node_Type is
      record
         Item      : List_Item;
         Ref_Count : Natural := 0;
         Next      : List_Type; -- or Node_Access?
      end record;


   function Get_Head
     (List : List_Type) return List_Item is
   begin
      return List.Head.Item;
   end;


   function Get_Item_Kind
     (Item : List_Item) return List_Item_Kind is
   begin
      return Item.Kind;
   end;

   function Get_Float_Item
     (Item : List_Item) return Float is
   begin
      return Item.F;
   end;


   procedure Adjust (List : in out List_Type) is
   begin
      null; -- adjust ref count
   end;


   procedure Finalize (List : in out List_Type) is
   begin
      null; -- adjust ref count
   end;


end Lists;













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

* Re: access to controlled types
  1999-02-20  0:00     ` Matthew Heaney
@ 1999-02-20  0:00       ` Matthew Heaney
  0 siblings, 0 replies; 8+ messages in thread
From: Matthew Heaney @ 1999-02-20  0:00 UTC (permalink / raw)


Matthew Heaney <matthew_heaney@acm.org> writes:

> "Terry J. Westley" <twestley@buffalo.veridian.com> writes:
> 
> > You have a good point.  I'll think about it a bit.  The specific
> > situation is that TASH supports Tcl lists which are heterogenous.
> > 
> > So, when you fetch an element out of the list, it could be an
> > integer, a float, a string, or another list.
> 
> 
> Can your list return a discriminated object? Something like the code
> below.

Actually, I thought of another way to do this, that doesn't require a
List_Item type in the spec.  Function Get_Head can just return the
different types (float, integer, string, list) directly, without the
intermediate type.  

If you know you have just floats, say, then you don't even have to
bother calling the Get_Item_Kind query function.

I don't really know if this is what you had in mind.  But if you want a
reference-counted list, then a private non-limited list type,
implemented as deriving from Controlled, is the way to go.  

This is one example of the fact that you do not have to expose access
types in the spec.  Access types are only for implementing abstractions,
and can thus be hidden from clients.  (There is one exception to this
rule.  See my post about the Interpreter pattern in the patterns archive
at the ACM, which uses an access type as a "handle," to point to a
limited and indefinite type.)



with Ada.Finalization;

package Lists2 is

   type List_Type is private;

   type List_Item_Kind is
      (Float_List_Item,
       Integer_List_Item,
       String_List_Item,
       List_List_Item);

   function Get_Item_Kind
     (List : List_Type) return List_Item_Kind;

   function Get_Head
     (List : List_Type) return Float;

   function Get_Head
     (List : List_Type) return Integer;

   function Get_Head
     (List : List_Type) return String;

   function Get_Head
     (List : List_Type) return List_Type;

private

   type Node_Type;
   type Node_Access is access Node_Type;

   type List_Type is
     new Ada.Finalization.Controlled with record
        Head : Node_Access;
     end record;

   procedure Adjust (List : in out List_Type);

   procedure Finalize (List : in out List_Type);


end Lists2;



 
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

package body Lists2 is

   type List_Item
     (Kind : List_Item_Kind := List_Item_Kind'First) is
      record
         case Kind is
            when Float_List_Item =>
               F : Float;

            when Integer_List_Item =>
               I : Integer;

            when String_List_Item =>
               S : Unbounded_String;

            when List_List_Item =>
               L : List_Type;

         end case;
      end record;


   type Node_Type is
      record
         Item      : List_Item;
         Ref_Count : Natural := 0;
         Next      : List_Type; -- or Node_Access?
      end record;


   function Get_Item_Kind
     (List : List_Type) return List_Item_Kind is
   begin
      return List.Head.Item.Kind;
   end;


   function Get_Head
     (List : List_Type) return Float is
   begin
      return List.Head.Item.F;
   end;


   function Get_Head
     (List : List_Type) return Integer is
   begin
      return List.Head.Item.I;
   end;


   function Get_Head
     (List : List_Type) return String is
   begin
      return To_String (List.Head.Item.S);
   end;


   function Get_Head
     (List : List_Type) return List_Type is
   begin
      return List.Head.Item.L;
   end;



   procedure Adjust (List : in out List_Type) is
   begin
      null; -- adjust ref count
   end;


   procedure Finalize (List : in out List_Type) is
   begin
      null; -- adjust ref count
   end;


end Lists2;




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

* Re: access to controlled types
  1999-02-03  0:00 access to controlled types Terry J. Westley
  1999-02-04  0:00 ` Stephen Leake
  1999-02-04  0:00 ` news.oxy.com
@ 1999-03-01  0:00 ` Matthew Heaney
  2 siblings, 0 replies; 8+ messages in thread
From: Matthew Heaney @ 1999-03-01  0:00 UTC (permalink / raw)


Look for my recent post about "smart pointers" in the ACM patterns
archive.  I show a technique that answers your question.



"Terry J. Westley" <twestley@buffalo.veridian.com> writes:

> In a new version of TASH, I've implmented an interface
> to Tcl objects (which are reference counted) with Ada
> controlled types.  I've been very impressed with how
> well this works in GNAT.
> 
> But, there are certain calls in the interface which
> return an access to a class-wide type.  It's easy to
> reference count these newly created objects, but since
> the access type is not controlled, the reference counts
> don't get decremented.  What's the solution?  Should I
> declare another controlled type which *contains* an
> access to the original controlled type?  Or, is there
> a better solution?






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

end of thread, other threads:[~1999-03-01  0:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-02-03  0:00 access to controlled types Terry J. Westley
1999-02-04  0:00 ` Stephen Leake
1999-02-05  0:00   ` Terry J. Westley
1999-02-20  0:00     ` Matthew Heaney
1999-02-20  0:00       ` Matthew Heaney
1999-02-04  0:00 ` news.oxy.com
1999-02-05  0:00   ` Garb Coll + Heap Cmpctn (was:access to controlled types) Nick Roberts
1999-03-01  0:00 ` access to controlled types Matthew Heaney

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