comp.lang.ada
 help / color / mirror / Atom feed
From: Craig Carey <research@ijs.co.nz>
Subject: Re: problem of read and write
Date: Fri, 13 Dec 2002 15:03:24 +1300
Date: 2002-12-13T15:03:24+13:00	[thread overview]
Message-ID: <eafivucl5ep8bvqg2djip40aoaous4q62f@4ax.com> (raw)
In-Reply-To: slrnave1q7.jk.lutz@taranis.iks-jena.de

On Wed, 11 Dec 2002 09:37:12 +0000 (UTC), Lutz Donnerhacke <lutz@iks-jena.de> wrote:

>* Francisco Santoyo wrote:
>> I have two tasks, one write[s] in some objects and the other read[s] from
>> them. 
>>
>> How can I avoid th[is:] the reader task read[s] the first object before...
>> the writer task [has] finish[ed]... writ[ing the first, some, or] the last?.
>
>Depending on your problem you can collect all those objects into a protected
>type or use a semaphore (also a protected type) to synchonize a long term
>access.

A sample program of reading and writing appears below.

This was my entry for the Computer Language Shootout contest of the
www.bagley.org website. The entry was rejected by a brief note I got in the
last week with the reasoning xplaining that the contest had closed last year.

The code here would be a solution to the Producer Consumer example of the
constest; and that example has a webpage here:

   http://www.bagley.org/~doug/shootout/bench/prodcons/


-------------------------------------------------------------------------------
with Text_IO, Ada.Command_Line;  --  Ref. http://www.bagley.org/~doug/shootout/
procedure Prodcons is            --  11-Dec-2002, coded in Ada 95
   type Buffer_Array is array (Positive range <>) of Integer;
   type Buffer_Array_Ptr is access Buffer_Array;
   Buffer               : Buffer_Array_Ptr;           --  Initialised to null
   Buffer_Closed_Error  : exception;
   protected Controller is
      entry Sample (Boolean) (Data : in out Integer);
      procedure Finish_Up;       --  (Calls don't queue on protected procedure)
   private                                --  (Guards can be not updated when
      Count       : Integer := 0;         --   only global variables change)
      Closed      : Boolean := False;
   end Controller;
   protected body Controller is        --  A family entry instead of 2 entries
      entry Sample (for Put_Not_Get in Boolean) (Data : in out Integer)
         when (Put_Not_Get and Count = 0) or          --  Block with 0% CPU use
              ((not Put_Not_Get) and (Count /= 0 or Closed)) is
      begin
         if Put_Not_Get then                             --  Add to the buffer
            Count := Count + 1;
            Buffer (Count) := Data;
         elsif Closed and Count = 0 then
            raise Buffer_Closed_Error;                   --  Raise an exception
         else                                            --  Take from buffer
            Data := Buffer (Count);
            Count := Count - 1;
         end if;
      end Sample;
      procedure Finish_Up is begin Closed := True; end Finish_Up;
   end Controller;
   Consumed, Produced   : Natural := 0;
   N, T1, T2, Chk       : Integer := 0;
begin
   if Ada.Command_Line.Argument_Count >= 1 then
      begin
         N := Natural'Max (0, Integer'Value (Ada.Command_Line.Argument (1)));
      exception      -- RM3.5(44) allows N to be negative if X'Max is omitted
         when Constraint_Error => N := 1;
      end;
   end if;
   Buffer := new Buffer_Array (1 .. N);   --  N can be 0 (and -1 would be OK)
   declare
      task Producer; task Consumer;          --  The tasks start when declared
      task body Producer is
      begin
         for I in 1 .. N loop
            T1 := I;                                        --  (I is constant)
            Controller.Sample (True) (Data => T1);
            Produced := Produced + 1;  Chk := Chk + I ** 3;
         end loop;                   --  Chk is OK despite overflow, no -gnato
         Controller.Finish_Up;
      end Producer;
      task body Consumer is
      begin
         loop
            begin
               Controller.Sample (False) (Data => T2);
               Consumed := Consumed + 1;  Chk := Chk - T2 ** 3;
            exception
               when Buffer_Closed_Error => exit;            --  Exit the loop
            end;
         end loop;            --  No "exit when K=N;" at bottom, to save a line
      end Consumer;           --  and the requirements seemed to allow that
   begin
      null;                   --  Wait here until the tasks have finished
   end;
   if Chk /= 0 then Text_IO.Put_Line ("Program_Error"); end if;   --  No probs
   Text_IO.Put_Line ("N =" & Integer'Image (N) & ": Produced =" & Natural'
            Image (Produced) & ", Consumed =" & Natural'Image (Consumed));
end Prodcons;
-------------------------------------------------------------------------------

That program seems to take about 12.7 secs per 1000 MHz of CPU power to get the
variable 'Produced' incremented up to 1,000,000, in Windows 2000 GNAT (with the
-O2 option), which seems very fast (at 12.7 microseconds), but it was not
ranking in the top 3.

THe Gcc entry has a loop around a mutex wait. Does someone know if that it is
actually a correct way to code when the operating system time slice interval is
bigger than 10 seconds. The Gcc entry did not contain any code to reduce the
operating system time slice interval thus I am unclear on whether it had a bug.



Craig Carey <research@ijs.co.nz>
Ada 95 mailing lists; http://www.ijs.co.nz/ada_95.htm








  reply	other threads:[~2002-12-13  2:03 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <mailman.1039593002.2252.comp.lang.ada@ada.eu.org>
2002-12-11  9:37 ` problem of read and write Lutz Donnerhacke
2002-12-13  2:03   ` Craig Carey [this message]
2002-12-13  4:51     ` Dennis Lee Bieber
2002-12-13 21:45     ` Dennis Lee Bieber
2002-12-13  8:19 Grein, Christoph
replies disabled

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