comp.lang.ada
 help / color / mirror / Atom feed
* Question about Finalization Control and reference counting
@ 2001-04-21 12:37 Preben Randhol
  2001-04-21 12:44 ` Preben Randhol
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Preben Randhol @ 2001-04-21 12:37 UTC (permalink / raw)



Hi

I'm wondering if it is possible to do something like this

   type Data_Type is new Ada.Finalization.Controlled with
      record
         References: Integer := 0;
   end record;
   
   type Data_Access_Type is access Data_Type;

[..]

and then in the main program if I do something like this:

   procedure main is

      Pointer : Data_Access_Type := null;
      Data : Data_Access_Type := new Data_Type;
   
   begin
   
      Pointer := Data; 

   end main;

to have Data.References increases by using Adjust? I'm trying but it
looks like it only works if I do:

   Pointer : Data_Type;
   ...
   Pointer := Data.all;
   ...
otherwise Adjust is not invoked. Is it possible to get it invoked if one
point an access type to an object? I'm trying to eliminate the problem
of dangling pointers in a program...

Thanks in advance.

-- 
Preben Randhol ------------------- http://www.pvv.org/~randhol/ --
                 �For me, Ada95 puts back the joy in programming.�



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

* Re: Question about Finalization Control and reference counting
  2001-04-21 12:37 Question about Finalization Control and reference counting Preben Randhol
@ 2001-04-21 12:44 ` Preben Randhol
  2001-04-24 16:11   ` Jeffrey Carter
  2001-04-24 16:10 ` Alexander Boucke
  2001-04-25  3:14 ` DuckE
  2 siblings, 1 reply; 11+ messages in thread
From: Preben Randhol @ 2001-04-21 12:44 UTC (permalink / raw)



To explain a bit more, I would like to have a doubled linked list with
nodes which contains pointers to the next and previous Node and the
content of the node pluss a reference count. If I want to remove a node
from the list I would like to only have to make the Node previous to
that point to the following node and the opposite. So that there are no
pointers pointing the the node I want to remove and then have Finalize
free-ing it. I'm not sure if this is possible or if I have to do it in
another way?

-- 
Preben Randhol ------------------- http://www.pvv.org/~randhol/ --
                 �For me, Ada95 puts back the joy in programming.�



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

* Re: Question about Finalization Control and reference counting
  2001-04-21 12:37 Question about Finalization Control and reference counting Preben Randhol
  2001-04-21 12:44 ` Preben Randhol
@ 2001-04-24 16:10 ` Alexander Boucke
  2001-04-25  3:14 ` DuckE
  2 siblings, 0 replies; 11+ messages in thread
From: Alexander Boucke @ 2001-04-24 16:10 UTC (permalink / raw)


Hello!

I managed to do this in a little more complicated way, but it works:


  type object is new ada.finalization.controlled with private;

-- some functions for object


private
  type handled_object is record
     ref_count : natural;
     -- other Data
  end record;

  type handled_object_access is access handled_object;

  type object is new ada.finalization.controlled with
     record
       the_object: handled_object_access;
     end record;

This way adjust and finalize are called for the type object and can access
object.the_objetc.ref_count.

I implemented a package doing vector- and matrix-algebra that way, since I
wanted to minimize the overhead of having temporary objects while evaluating
statements like a:=b+c; and did not want to think about handling pointers
all the time. It even allowed me to write some sort of caching technique to
reuse some vectors.

There is probably an easier way to implement this, if somebody has one...

Regards,

Alexander Boucke





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

* Re: Question about Finalization Control and reference counting
  2001-04-21 12:44 ` Preben Randhol
@ 2001-04-24 16:11   ` Jeffrey Carter
  2001-04-25 15:58     ` Preben Randhol
  2001-04-25 16:57     ` Stanley R. Allen
  0 siblings, 2 replies; 11+ messages in thread
From: Jeffrey Carter @ 2001-04-24 16:11 UTC (permalink / raw)


Adjust only applies to a controlled type, so you need to put your access
value inside a controlled type:

type Node;

type Node_Ptr is access all Node;

type Node is new [Limited_]Controlled with record
   Prev  : Node_Ptr;
   Data  : Whatever;
   Count : Natural := 0;
   Next  : Node_Ptr;
end record;

procedure Adjust (Object : in out Node);

procedure Finalize (Object : in out Node);

For a doubly linked list like this, you probably don't need a reference
count or Adjust. See the PragmAda Reusable Components
(PragmARC.List_Unbounded_Unprotected) for just such a list.



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

* Re: Question about Finalization Control and reference counting
  2001-04-21 12:37 Question about Finalization Control and reference counting Preben Randhol
  2001-04-21 12:44 ` Preben Randhol
  2001-04-24 16:10 ` Alexander Boucke
@ 2001-04-25  3:14 ` DuckE
  2 siblings, 0 replies; 11+ messages in thread
From: DuckE @ 2001-04-25  3:14 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2942 bytes --]

Try placing the access variable inside the protected type:

package Managed_Allocation is

  type Node is private;

  function New_Node return Node;

private
  type Node_Data is
     record
        Reference_Count : Natural := 0;
     end record;

  type Node_Data_Access is access all Node_Data;

  type Node is new Ada.Finalization.Controlled with
     record
        Node_Data_Ref : Node_Data_Access;
     end record;

  procedure Initialize (
        Object : in out Node );
  procedure Adjust (
        Object : in out Node );
  procedure Finalize (
        Object : in out Node );

end Managed_Allocation;

with Ada.Unchecked_Deallocation;

package body Managed_Allocation is

  function New_Node return Node is
    Data_Node : Node;
  begin
    Data_Node.Node_Data_Ref := new Node_Data;
    return Data_Node;
  end New_Node;

  procedure Free is
  new Ada.Unchecked_Deallocation( Node_Data, Node_Data_Access );

  procedure Initialize (
        Object : in out Node ) is
  begin
    Object .Node_Data_Ref := null;
  end Initialize;

  procedure Adjust (
        Object : in out Node ) is
  begin
    if Object .Node_Data_Ref /= null then
      Object.Node_Data_Ref.Reference_Count := Object .Node_Data_Ref.
        Reference_Count + 1;
    end if;
  end Adjust;

  procedure Finalize (
        Object : in out Node ) is
  begin
    if Object.Node_Data_Ref /= null then
      Object.Node_Data_Ref.Reference_Count := Object.Node_Data_Ref.
        Reference_Count - 1;
      if Object .Node_Data_Ref.Reference_Count = 0 then
        Free( Object .Node_Data_Ref );
        Object .Node_Data_Ref := null;
      end if;
    end if;
  end Finalize;

end Managed_Allocation;


BTW: I didn't check, but you can probably find another example of this at:
  www.adapower.com

SteveD

"Preben Randhol" <randhol+abuse@pvv.org> wrote in message
news:slrn9e2vqb.aah.randhol+abuse@kiuk0156.chembio.ntnu.no...
>
> Hi
>
> I'm wondering if it is possible to do something like this
>
>    type Data_Type is new Ada.Finalization.Controlled with
>       record
>          References: Integer := 0;
>    end record;
>
>    type Data_Access_Type is access Data_Type;
>
> [..]
>
> and then in the main program if I do something like this:
>
>    procedure main is
>
>       Pointer : Data_Access_Type := null;
>       Data : Data_Access_Type := new Data_Type;
>
>    begin
>
>       Pointer := Data;
>
>    end main;
>
> to have Data.References increases by using Adjust? I'm trying but it
> looks like it only works if I do:
>
>    Pointer : Data_Type;
>    ...
>    Pointer := Data.all;
>    ...
> otherwise Adjust is not invoked. Is it possible to get it invoked if one
> point an access type to an object? I'm trying to eliminate the problem
> of dangling pointers in a program...
>
> Thanks in advance.
>
> --
> Preben Randhol ------------------- http://www.pvv.org/~randhol/ --
>                  �For me, Ada95 puts back the joy in programming.�





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

* Re: Question about Finalization Control and reference counting
@ 2001-04-25 11:08 Christoph Grein
  0 siblings, 0 replies; 11+ messages in thread
From: Christoph Grein @ 2001-04-25 11:08 UTC (permalink / raw)
  To: comp.lang.ada

There is a package called Safe_Pointers in my home page. It was published some 
time ago in Ada Letters. It implements reference-counted pointers: Data is 
allocated once and deallocated only if there are not pointers left. You can use 
it as a reusable component instead of Ada's access types. It comes with full 
documentation (i.e. a copy of the Ada Letters article).

http://home.T-Omline.de/home/Christ-Usch.Grein/Ada/





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

* Re: Question about Finalization Control and reference counting
  2001-04-24 16:11   ` Jeffrey Carter
@ 2001-04-25 15:58     ` Preben Randhol
  2001-04-25 16:01       ` Preben Randhol
  2001-04-25 22:22       ` Jeffrey Carter
  2001-04-25 16:57     ` Stanley R. Allen
  1 sibling, 2 replies; 11+ messages in thread
From: Preben Randhol @ 2001-04-25 15:58 UTC (permalink / raw)


On Tue, 24 Apr 2001 16:11:33 GMT, Jeffrey Carter wrote:
> Adjust only applies to a controlled type, so you need to put your access
> value inside a controlled type:
> 
> type Node;
> 
> type Node_Ptr is access all Node;
> 
> type Node is new [Limited_]Controlled with record
>    Prev  : Node_Ptr;
>    Data  : Whatever;
>    Count : Natural := 0;
>    Next  : Node_Ptr;
> end record;
> 
> procedure Adjust (Object : in out Node);
> 
> procedure Finalize (Object : in out Node);


But the problem is that if you have :

   Node1 : Node_Ptr;
   Node2 : Node_Ptr;
   Node3 : Node;

   ...

   After making the Nodes with new you:

   Node1.Next := Node2;

   Then Adjust of Node2 won't be called it will only be called if you
   do:

   Node3 := Node1.all;

   if I understand things correctly. I think I need to rethink my
   problem in a more Ada approach :-)


-- 
Preben Randhol ------------------- http://www.pvv.org/~randhol/ --
                 �For me, Ada95 puts back the joy in programming.�



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

* Re: Question about Finalization Control and reference counting
  2001-04-25 15:58     ` Preben Randhol
@ 2001-04-25 16:01       ` Preben Randhol
  2001-04-25 22:22       ` Jeffrey Carter
  1 sibling, 0 replies; 11+ messages in thread
From: Preben Randhol @ 2001-04-25 16:01 UTC (permalink / raw)


On Wed, 25 Apr 2001 15:58:33 +0000 (UTC), Preben Randhol wrote:
>    Then Adjust of Node2 won't be called it will only be called if you
>    do:
> 
>    Node3 := Node1.all;

Oops I meant: Node3 := Node2.all;

-- 
Preben Randhol ------------------- http://www.pvv.org/~randhol/ --
                 �For me, Ada95 puts back the joy in programming.�



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

* Re: Question about Finalization Control and reference counting
  2001-04-24 16:11   ` Jeffrey Carter
  2001-04-25 15:58     ` Preben Randhol
@ 2001-04-25 16:57     ` Stanley R. Allen
  1 sibling, 0 replies; 11+ messages in thread
From: Stanley R. Allen @ 2001-04-25 16:57 UTC (permalink / raw)


Jeffrey Carter wrote:
> 
> type Node;
> type Node_Ptr is access all Node;
> type Node is new [Limited_]Controlled with record
>    [slice]
> procedure Adjust (Object : in out Node);

But.....

if it's derived from Limited_Controlled, the Adjust procedure
(though permitted) will never be 'automatically' invoked.

-- 
Stanley Allen
mailto:Stanley_R_Allen-NR@raytheon.com



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

* Re: Question about Finalization Control and reference counting
  2001-04-25 15:58     ` Preben Randhol
  2001-04-25 16:01       ` Preben Randhol
@ 2001-04-25 22:22       ` Jeffrey Carter
  2001-04-26  8:50         ` Preben Randhol
  1 sibling, 1 reply; 11+ messages in thread
From: Jeffrey Carter @ 2001-04-25 22:22 UTC (permalink / raw)


Preben Randhol wrote:
> 
> On Tue, 24 Apr 2001 16:11:33 GMT, Jeffrey Carter wrote:
> > Adjust only applies to a controlled type, so you need to put your access
> > value inside a controlled type:
> >
> > type Node;
> >
> > type Node_Ptr is access all Node;
> >
> > type Node is new [Limited_]Controlled with record
> >    Prev  : Node_Ptr;
> >    Data  : Whatever;
> >    Count : Natural := 0;
> >    Next  : Node_Ptr;
> > end record;
> >
> > procedure Adjust (Object : in out Node);
> >
> > procedure Finalize (Object : in out Node);
> 
> But the problem is that if you have :
> 
>    Node1 : Node_Ptr;
>    Node2 : Node_Ptr;
>    Node3 : Node;
> 
>    ...
> 
>    After making the Nodes with new you:
> 
>    Node1.Next := Node2;
> 
>    Then Adjust of Node2 won't be called it will only be called if you
>    do:
> 
>    Node3 := Node1.all;
> 
>    if I understand things correctly. I think I need to rethink my
>    problem in a more Ada approach :-)

Perhaps I'm trying to be too user friendly. Or maybe I'm failing. For a
real list component, Node would not be controlled, but the list type
would.

A list component will generally not make its access type visible to its
clients. All modification of a list will be through the operations
provided, so freeing space when a node is deleted can be handled
properly through those operations. You would rather want to define
Adjust and Finalize for an entire List, to ensure that memory is managed
properly.

If you do really want to control individual nodes, then you need to
replace the access type with a "smart pointer", an access value inside a
controlled type that points to an object with a reference count. Adjust
would increment the count, and Finalize would decrement it and
deallocate the object when it reaches zero. Then

Node1.Next := Node2;

will Finalize Node1 and Adjust its new value. However, to access the
node directly, you have to say

Node.Value.all.

--
Jeff Carter



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

* Re: Question about Finalization Control and reference counting
  2001-04-25 22:22       ` Jeffrey Carter
@ 2001-04-26  8:50         ` Preben Randhol
  0 siblings, 0 replies; 11+ messages in thread
From: Preben Randhol @ 2001-04-26  8:50 UTC (permalink / raw)


On Wed, 25 Apr 2001 22:22:15 GMT, Jeffrey Carter wrote:
> 
> Perhaps I'm trying to be too user friendly. Or maybe I'm failing. For a
> real list component, Node would not be controlled, but the list type
> would.
> 
> A list component will generally not make its access type visible to its
> clients. All modification of a list will be through the operations
> provided, so freeing space when a node is deleted can be handled
> properly through those operations. You would rather want to define
> Adjust and Finalize for an entire List, to ensure that memory is managed
> properly.

Yes :-) After thinking a bit yesterday I did exactly this :-). Made the
Node types all private and added an itterator to the List so I can do:

Goto_First (List); Goto_Next (List); Goto_Previous (List); Goto_Last (List);

etc... (Prepending Goto so I don't mess with possible variable name space.)

and then I have : Get_Element (List) return Data_Type; which gives the
Data_Type (not the access value) in the Node the itterator is pointing
at at the moment.

As the Data_Type is generic it will then be up to the user to apply
Finaliaztion control on the Data_Type and then everything is ok if I
remove a Node.

Now I'll add Finalization to the List object :-)


Thanks everybody for much valued help!

-- 
Preben Randhol ------------------- http://www.pvv.org/~randhol/ --
                 �For me, Ada95 puts back the joy in programming.�



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

end of thread, other threads:[~2001-04-26  8:50 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-04-21 12:37 Question about Finalization Control and reference counting Preben Randhol
2001-04-21 12:44 ` Preben Randhol
2001-04-24 16:11   ` Jeffrey Carter
2001-04-25 15:58     ` Preben Randhol
2001-04-25 16:01       ` Preben Randhol
2001-04-25 22:22       ` Jeffrey Carter
2001-04-26  8:50         ` Preben Randhol
2001-04-25 16:57     ` Stanley R. Allen
2001-04-24 16:10 ` Alexander Boucke
2001-04-25  3:14 ` DuckE
  -- strict thread matches above, loose matches on Subject: below --
2001-04-25 11:08 Christoph Grein

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