----------------------------------------------------------------------
-- Aufgabe: summiere 1..n.
-- Methode: tasks fuer Teilsummen 1..n/2, n/2+1..n falls n>50,
--          erste task erzeugt und startet die zweite und bildet
--          Gesamtergebnis
----------------------------------------------------------------------

with Stringpack; use Stringpack;
procedure Arbeitsteilung3 is

   task Worker is
      entry Start(From, To: Integer);
      entry Result(Res: out Integer);
   end Worker;

   task type Helper is
      entry Start(From, To: Integer);
      entry Result(Res: out Integer);
   end Helper;

   type Helper_Ptr is access Helper;

   task body Worker is
      Local_From, Local_To: Integer;
      Local_Res, Remote_Res: Integer := 0;
      H: Helper_Ptr;
   begin
      accept Start(From, To: Integer) do
         Local_From := From;
         Local_To := To;
      end Start;
      if Local_To-Local_From >50 then
         H := new Helper;
         H.Start(Local_From, (Local_From+Local_To)/2);
         for I in ((Local_From + Local_To)/2 +1)..Local_To loop
            Local_Res := Local_Res+I;
         end loop;
         H.Result(Remote_Res);
      else
         for I in Local_From+Local_To..Local_To loop
            Local_Res := Local_Res + 1;
         end loop;
      end if;
      accept Result(Res: out Integer) do
         Res := Local_Res + Remote_Res;
      end Result;
   end Worker;

   task body Helper is
      Local_From, Local_To, Local_Res: Integer;
   begin
      accept Start(From, To: Integer) do
         Local_From := From;
         Local_To := To;
      end Start;
      Local_Res := 0;
      for I in Local_From..Local_To loop
         Local_Res := Local_Res+I;
      end loop;
      accept Result(Res: out Integer) do
         Res := Local_Res;
      end Result;
   end Helper;

   N, Sum: Integer;

begin
   Print("give natural");
   N := Getint;
   Worker.Start(1, N);
   Worker.Result(Sum);
   Print("Summe= " & Sum);
end Arbeitsteilung3;

