comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Impossible problem? A protected buffer to queue objects of a class-wide type
Date: Wed, 11 Apr 2007 15:14:52 +0200
Date: 2007-04-11T15:14:52+02:00	[thread overview]
Message-ID: <1l084b788szi.f2wv40cu74ci$.dlg@40tude.net> (raw)
In-Reply-To: 461cc46d$1_1@glkas0286.greenlnk.net

On Wed, 11 Apr 2007 12:34:15 +0100, Phil Slater wrote:

> I've hit a brick wall. Every strategy I try doesn't work.
> 
> I need to write a generic package that exports a protected queue type that 
> will act as a buffer for objects of a class-wide type. My strategy is that 
> when objects join the queue they are copied onto the heap, and an 
> access-to-class-wide value is put onto the queue (could be array-based or 
> linked-list-based - I don't mind). To retrieve an item from the queue, an 
> access-to-class-wide value is removed from the queue, the heap object it 
> designates is copied onto the stack, the heap object is deallocated, then 
> the copy is returned.

> The crux of the problem goes like this:
> 
> (a) for the client code to retrieve an item, it needs to call a function; it 
> can't be done through a procedure or entry "out" parameter since I can't 
> declare an uninitialised variable of the class-wide type to pass as an 
> actual parameter. So the client code needs to do something like this:
>     declare
>         Next_In_Line : Item'class := My_Buffer.Dequeue;  -- My_Buffer is the 
> protected queue
> 
> (b) To support this call, Dequeue must be written as a function. As such, it 
> cannot change the protected queue. What I need is the "entry" functionality, 
> since I want the Dequeue to wait if the queue is empty, and I want the item 
> to be removed from the queue as well as retrieved.
> 
> (c) In a non-concurrent environment, I would simply write two separate 
> operations on the queue: a function Read_Next_Item and a procedure 
> Delete_Next_Item, which the client code would call in turn. However, that's 
> no good in a concurrent environment - two tasks could both call 
> Read_Next_Item before the first has had a chance to call Delete_Next_Item, 
> so the same item is read twice and the following item is skipped.
> 
> I really do want all the heap operations through the access-to-class-wide 
> type to be hidden away in the package - I did consider writing a protected 
> buffer with an entry whose out parameter was an access-to-class-wide type, 
> but this is highly unsatisfactory as it puts the onus for deallocating heap 
> space into the client code - very messy.
> 
> I cannot see a way through this problem, and am astounded that a language of 
> this calibre seems to have rules that conspire together to make it appear 
> impossible. What have I missed?

There are many ways to solve this.

1. You can wrap My_Buffer into a normal limited type. This will allow you
to have functions returning a class-wide:

   function Get_Next (Buffer : access My_Buffer_Interface)
      return Item'Class;

The implementation of Get_Next will go as follows:

function Get_Next (Buffer : access My_Buffer_Interface)
   return Item'Class is
   procedure Free is new Ada.Unchecked_Deallocation (Item, Item_Ptr);
   Ptr : Item_Ptr;
begin
   Buffer.Implementation.Get_Next (Ptr);
       -- Protected operation which takes pointer out of the buffer
       -- Buffer.Implementation is your protected queue
   declare -- In Ada 2005 it could be done better, I suppose
      This : Item'Class := Ptr.all;
   begin
      Free (Ptr);
      return This;
   end;
end Get_Next;

2. You use smart pointers to Item'Class instead of the items themselves. So
you will marshal only pointers through the queue and not the objects
themselves. This would reduce overhead of item's copying upon marshaling.
Deallocation will be handled by the smart pointer. Provided that items are
not accessed concurrently you will not need to interlock on pointer
dereferencing. Additional advantage is an ability to use limited items. [An
implementation of smart pointers can be found in Simple Components.]

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



  parent reply	other threads:[~2007-04-11 13:14 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-11 11:34 Impossible problem? A protected buffer to queue objects of a class-wide type Phil Slater
2007-04-11 12:25 ` Rob Norris
2007-04-11 13:02   ` Phil Slater
2007-04-12  8:36     ` Stephen Leake
2007-04-11 13:14 ` Dmitry A. Kazakov [this message]
2007-04-11 14:01 ` Jean-Pierre Rosen
2007-04-11 17:18 ` tmoran
2007-04-13 17:02 ` Matthew Heaney
2007-04-13 17:26   ` Matthew Heaney
2007-04-13 17:36   ` Ed Falis
replies disabled

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