----------------------------------------------------------------------
-- Aufgabe: producer-consumer (summation_of_naturals) with bounded buffer
-- Methode: tasks for producer-consumer (simple sum_of_naturals problem)
--          protected object for buffer
----------------------------------------------------------------------

with Stringpack; use Stringpack;
procedure Bounded_Buffer is

   Length: constant Natural := 10;
   type Buff_Type is array(0..Length-1) of Natural;

   protected Buffer is
      entry Insert(D: Natural);
      entry Take(D: out Natural);
   private
      B: Buff_Type;
      In_Ptr, Out_Ptr: Natural := 0;
      Count: Natural := 0;
   end Buffer;

   task Producer is
      entry Start(How_Many: Natural);
   end Producer;

   task Consumer is
      entry Start(Break: Natural);
   end Consumer;

   task body Producer is
      Local_How_Many: Natural;
   begin
      accept Start(How_Many: Natural) do
         Local_How_Many := How_Many;
      end Start;

      Consumer.Start(Local_How_Many+1);

      for I in 1.. (Local_How_Many+1) loop
         Buffer.Insert(I);
      end loop;
   end Producer;

   task body Consumer is
      Over, Item, Result: Natural;
   begin
      accept Start(Break: Natural) do
         Over := Break;
      end Start;

      Result := 0;
      Buffer.Take(Item);
      while Item /= Over loop
         Result := Result+Item;
         Buffer.Take(Item);
      end loop;
      Print("Summe= " & Result);
   end Consumer;

   protected body Buffer is
      entry Insert(D: Natural)
        when Count < Length is
      begin
         B(In_Ptr) := D;
         In_Ptr := (In_Ptr +1) mod Length;
         Count := Count +1;
      end Insert;

      entry Take(D: out Natural)
        when Count > 0 is
      begin
         D := B(Out_Ptr);
         Out_Ptr := (Out_Ptr +1) mod Length;
         Count := Count -1;
      end Take;
   end Buffer;

   N: Natural;

begin
   Print("give natural");
   N := Getint;
   Producer.Start(N);
end Bounded_Buffer;


