From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Ravenscar-compliant bounded buffer
Date: Wed, 5 Sep 2007 09:46:39 +0200
Date: 2007-09-05T09:46:10+02:00 [thread overview]
Message-ID: <1xnpics66h1c9.js3eyt5bsx1e.dlg@40tude.net> (raw)
In-Reply-To: GKadnVsMGJJdhkPbnZ2dnUVZ_hadnZ2d@comcast.com
On Tue, 4 Sep 2007 20:00:13 -0700, Steve wrote:
> While I don't know much about the Ravenscar profile (other than what it is)
> I am famialar with the use of protected types.
>
> The sample code is a good illustration of "abstraction inversion". I know
> this because I posted similar code on this group several years ago and that
> is how it was described.
>
> The code uses a high level abstraction "protected type" to create a low leve
> abstraction "Binary_Semaphore". The code uses two semaphores to restrict
> access to the bounded buffer. In this simple example it is easy to follow,
> but in a more complex example pairing Acquire's and Release's can be a
> chore.
That is because of the Ravenscar limitation of one entry per protected
object. The solution Maciej presented is based on splitting one protected
object of two entries into two, each controlling access to its end of FIFO.
Protected objects don't compose so the result. Worse it will be with FIFO
size > 1.
Here is a solution based on event + requeue rather than mutexes. Requeue is
implicit of course, because Ravenscar forbids requeue statements.
pragma Profile (Ravenscar);
package Bounded_Buffer is
subtype Multiple is Positive range 2..Positive'Last;
type Buffer_Type (Size : Multiple) is limited private;
procedure Get (Buffer : in out Buffer_Type; Item : out Integer);
procedure Put (Buffer : in out Buffer_Type; Item : Integer);
private
type Storage_Data is array (Positive range <>) of Integer;
protected type Buffer_Type (Size : Multiple) is
entry Wait;
procedure Get (Item : out Integer; Success : out Boolean);
procedure Put (Item : Integer; Success : out Boolean);
private
Storage : Storage_Data (1..Size);
First_In : Positive := 1;
First_Out : Positive := 1;
Empty : Boolean := True;
Free : Boolean := False; -- In /= Out explicitly
end Buffer_Type;
end Bounded_Buffer;
Notes:
1. First_In /= First_Out is a complex barrier, so we need it explicitly as
Free.
2. With buffer size 1 this implementation would do busy waiting, for this
reason the minimal buffer size is 2.
package body Bounded_Buffer is
protected body Buffer_Type is
entry Wait when Free is
begin
null;
end Wait;
procedure Put (Item : in Integer; Success : out Boolean) is
begin
if Free or else Empty then
Storage (First_Out) := Item;
if First_Out = Size then
First_Out := 1;
else
First_Out := First_Out + 1;
end if;
Free := First_Out /= First_In;
Empty := False;
Success := True;
else
Success := False;
end if;
end Put;
procedure Get (Item : out Integer; Success : out Boolean) is
begin
if Free or else not Empty then
Item := Storage (First_In);
if First_In = Size then
First_In := 1;
else
First_In := First_In + 1;
end if;
Free := First_Out /= First_In;
Empty := not Free;
Success := True;
else
Success := False;
end if;
end Get;
end Buffer_Type;
procedure Put (Buffer : in out Buffer_Type; Item : in Integer) is
Success : Boolean;
begin
loop
Buffer.Put (Item, Success);
exit when Success;
Buffer.Wait;
end loop;
end Put;
procedure Get (Buffer : in out Buffer_Type; Item : out Integer) is
Success : Boolean;
begin
loop
Buffer.Get (Item, Success);
exit when Success;
Buffer.Wait;
end loop;
end Get;
end Bounded_Buffer;
-----------------------
P.S. As a general note. This object might interesting as an exercise, but
not likely needed. In a real application it would be strange to expect
multiple consumers taking integers out of buffer in some unpredictable
order. Normally, it is so that either there is one producer and one or many
consumers (like in distribution of jobs), or else there is many producers
and one consumer (like writing to log file). This might sufficiently
simplify the design. Yet another variant is multiple consumers receiving
whole waveform of integers put to the buffer (broadcasting). This would be
more difficult.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
next prev parent reply other threads:[~2007-09-05 7:46 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-04 13:53 Ravenscar-compliant bounded buffer Maciej Sobczak
2007-09-05 3:00 ` Steve
2007-09-05 7:38 ` Maciej Sobczak
2007-09-06 4:04 ` Steve
2007-09-06 14:06 ` Robert A Duff
2007-09-06 15:36 ` Dmitry A. Kazakov
2007-09-07 2:36 ` Robert A Duff
2007-09-06 21:13 ` Maciej Sobczak
2007-09-07 2:41 ` Robert A Duff
2007-09-07 11:56 ` anon
2007-09-07 19:44 ` Maciej Sobczak
2007-09-08 0:16 ` anon
2007-09-08 1:19 ` Larry Kilgallen
2007-09-08 5:13 ` anon
2007-09-08 22:06 ` Larry Kilgallen
2007-09-09 2:17 ` anon
2007-09-09 12:07 ` Larry Kilgallen
2007-09-09 13:10 ` Markus E L
2007-09-11 2:44 ` Randy Brukardt
2007-09-08 11:50 ` Niklas Holsti
2007-09-08 12:01 ` Pascal Obry
2007-09-08 17:13 ` anon
2007-09-08 17:11 ` anon
2007-09-08 19:14 ` Markus E L
2007-09-09 14:54 ` anon
2007-09-09 16:01 ` Markus E L
2007-09-09 10:38 ` Gautier
2007-09-09 11:41 ` anon
2007-09-09 13:19 ` Markus E L
2007-09-09 13:52 ` Pascal Obry
2007-09-09 15:22 ` anon
2007-09-09 16:03 ` Markus E L
2007-09-10 0:05 ` Larry Kilgallen
2007-09-10 3:10 ` Markus E L
2007-09-09 16:05 ` Markus E L
2007-09-09 18:40 ` Ed Falis
2007-09-09 19:11 ` Markus E L
2007-09-09 10:57 ` Gautier
2007-09-09 14:49 ` anon
2007-09-09 15:08 ` Pascal Obry
2007-09-09 15:38 ` Markus E L
2007-09-09 19:12 ` Niklas Holsti
2007-09-09 19:28 ` Ed Falis
2007-09-10 12:51 ` Colin Paul Gloster
2007-09-07 1:38 ` Steve
2007-09-07 2:47 ` Robert A Duff
2007-09-05 7:46 ` Dmitry A. Kazakov [this message]
2007-09-05 8:17 ` brodax
2007-09-05 8:30 ` Jean-Pierre Rosen
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox