comp.lang.ada
 help / color / mirror / Atom feed
From: "Nick Roberts" <nickroberts@callnetuk.com>
Subject: Re: How can I avoid Using a Semaphore?
Date: Mon, 15 Jan 2001 01:06:08 -0000
Date: 2001-01-15T01:06:08+00:00	[thread overview]
Message-ID: <93ti8b$bjpps$1@ID-25716.news.dfncis.de> (raw)
In-Reply-To: cd%76.260429$U46.8278617@news1.sttls1.wa.home.com

Please find attached my first quick attempt at a slightly neater solution.
It's untested, so don't say I didn't warn you!

The essential idea is that the task reading the socket does something like
this:

   loop
      get length of buffer
      call Create to allocate a buffer in the queue (and in memory)
      read data into buffer
      call Commit to allow other tasks to obtain the buffer
   end loop

Each task handling messages does the following:

   loop
      call Obtain to get an unprocessed buffer
      process the buffer as required
      call Delete to release the buffer (from the queue and memory)
   end loop

Does this vaguely cut it?

I use the trick of passing out a 'token' from Create and Obtain, which is
passed into Commit or Delete to identify the buffer in the queue. Create and
Obtain are both entries: Create blocks whilst the queue is full; Obtain
blocks whilst there are no buffers in the queue awaiting processing. There
can be any number of message-handling tasks, as they will be arbitrated
between properly by their calls to Obtain.

Of course, the call to Commit is very like clearing a semaphore to permit
the second phase of processing of a buffer.

Now I come to think of it, buffers are obtained from the queue in no
particular order, so 'queue' is the wrong term, really. Perhaps
Protected_Array_Queueing isn't really the right name for this package. Maybe
Buffer_Pooling or Buffer_Distribution would be better. (Or Grab_Bag? ;-)

--
Nick Roberts
http://www.AdaOS.org


"DuckE" <nospam_steved94@home.com> wrote in message
news:cd%76.260429$U46.8278617@news1.sttls1.wa.home.com...
> I have an application that receives a streams of data from TCP/IP sockets.
> The stream of data is separated into "packets" each beginning with a 32
bit
> length value.
> ...




=====
-- (c) 2000 Nicholas James Roberts
-- All rights in this work are hereby granted into the PUBLIC DOMAIN
-- by the author. The author asserts his moral rights over this work.

generic
   type Datum_Type is private;

package Protected_Array_Queueing is

   type Data_Array is array (Positive range <>) of Datum_Type;

   type Array_Access is access Data_Array;

   type Buffer_Token is private;

   -- Convenience declarations:
   type Array_Access_Array is array (Positive range <>) of Array_Access;
   type Boolean_Array is array (Positive range <>) of Boolean;

   protected type Buffer_Queue (Capacity: Natural) is

      entry Create (Length: in  Natural;
                    Token:  out Buffer_Token;
                    Buffer: out Array_Access);

      procedure Commit (Token: in Buffer_Token);

      entry Obtain (Token:  out Buffer_Token;
                    Buffer: out Array_Access);

      procedure Delete (Token: in Buffer_Token);

      procedure Reset;

   private
      Queue:       Array_Access_Array(1..Capacity);
      Allocated:   Boolean_Array(1..Capacity) := (others => False);
      Available:   Boolean_Array(1..Capacity) := (others => False);
      Create_Here: Positive := 1;
      Obtain_Here: Positive := 1;
      Alloc_Count: Natural := 0;
      Avail_Count: Natural := 0;

   end Buffer_Queue;

   Invalid_Token: exception;

private

   type Buffer_Token is new Positive;

end Protected_Array_Queueing;


=====
with Unchecked_Deallocation;

package body Protected_Array_Queueing is

   procedure Free is new Unchecked_Deallocation(Data_Array,Array_Access);

   protected body Buffer_Queue is

      function Next (Here: in Positive) return Positive is
      begin
         if Here = Capacity then
            return 1;
         else
            return Here+1;
         end if;
      end Next;

      entry Create (Length: in  Natural;
                    Token:  out Buffer_Token;
                    Buffer: out Array_Access) when Alloc_Count < Capacity is
      begin
         while Allocated(Create_Here) loop
            Create_Here := Next(Create_Here);
         end loop;
         Token := Buffer_Token(Create_Here);
         Buffer := new Data_Array(1..Length);
         Queue(Create_Here) := Buffer;
         Alloc_Count := Alloc_Count+1;
         Allocated(Create_Here) := True;
         Available(Create_Here) := False;
      end Create;

      procedure Commit (Token: in Buffer_Token) is
         Commit_Here: Positive range 1..Capacity := Positive(Token);
      begin
         if not Allocated(Commit_Here) then
            raise Invalid_Token;
         end if;
         if not Available(Commit_Here) then
            Available(Commit_Here) := True;
            Avail_Count := Avail_Count+1;
         end if;
      end Commit;

      entry Obtain (Token:  out Buffer_Token;
                    Buffer: out Array_Access) when Avail_Count > 0 is
      begin
         while not Available(Obtain_Here) loop
            Obtain_Here := Next(Obtain_Here);
         end loop;
         Token := Buffer_Token(Obtain_Here);
         Buffer := Queue(Obtain_Here);
         Avail_Count := Avail_Count-1;
         Available(Obtain_Here) := False;
      end Obtain;

      procedure Delete (Token: in Buffer_Token) is
         Delete_Here: Positive range 1..Capacity := Positive(Token);
      begin
         if not Allocated(Delete_Here) then
            raise Invalid_Token;
         end if;
         Free(Queue(Delete_Here)); -- Queue(Delete_Here) := null;
         if Available(Delete_Here) then
            Avail_Count := Avail_Count-1;
         end if;
         Allocated(Delete_Here) := False;
         Alloc_Count := Alloc_Count-1;
      end Delete;

      procedure Reset is
      begin
         for i in 1..Capacity loop
            Free(Queue(i)); -- Queue(i) := null;
         end loop;
         Allocated   := (others => False);
         Available   := (others => False);
         Create_Here := 1; -- not really necessary
         Obtain_Here := 1; -- not really necessary
         Alloc_Count := 0;
         Avail_Count := 0;
      end Reset;

   end Buffer_Queue;

end Protected_Array_Queueing;






  reply	other threads:[~2001-01-15  1:06 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-01-13 16:18 How can I avoid Using a Semaphore? (long) DuckE
2001-01-15  1:06 ` Nick Roberts [this message]
2001-01-15  3:17   ` How can I avoid Using a Semaphore? Robert Dewar
2001-01-16  3:53   ` DuckE
2001-01-17 15:42     ` Nick Roberts
2001-01-20 18:16       ` DuckE
2001-01-20 19:16         ` Robert Dewar
2001-01-21  1:28           ` DuckE
2001-01-21 16:04             ` Robert Dewar
2001-01-21 23:23               ` DuckE
2001-01-22  0:28                 ` mark_lundquist
2001-01-22  1:51                 ` Robert Dewar
2001-01-23  2:36                   ` DuckE
2001-01-22  0:35               ` Built-in types (was " mark_lundquist
2001-01-22  1:54                 ` Robert Dewar
2001-01-22 16:18                   ` mark_lundquist
2001-01-22 17:20                     ` Robert Dewar
2001-01-22 23:17                       ` Mark Lundquist
     [not found]                         ` <m33deaaeks.fsf@ns40.infomatch.bc.ca>
2001-02-02 22:01                           ` Mark Lundquist
     [not found]                         ` <94km00$bv8$1@nnrp1.deja.com>
2001-02-02 22:03                           ` Mark Lundquist
2001-01-21 16:53           ` Nick Roberts
2001-01-21 18:24             ` Robert Dewar
2001-01-23  0:21               ` Nick Roberts
2001-01-22  0:16         ` mark_lundquist
2001-01-22 16:51 ` How can I avoid Using a Semaphore? (long) mark_lundquist
2001-01-23  6:02   ` DuckE
2001-02-02 22:00     ` Sucking (was Re: How can I avoid Using a Semaphore? (long)) Mark Lundquist
2001-02-03  1:44       ` Jeffrey Carter
2001-02-03  3:21       ` DuckE
2001-02-05 20:07         ` Mark Lundquist
2001-02-06  7:16           ` Sven Nilsson
2001-02-02 22:18     ` How can I avoid Using a Semaphore? (long) Mark Lundquist
2001-02-03  3:01       ` DuckE
2001-02-02 21:38 ` Niklas Holsti
replies disabled

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