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;
next prev parent 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