comp.lang.ada
 help / color / mirror / Atom feed
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



  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