----------------------------------------------------------------------
-- Aufgabe: summiere 1..n.
-- Methode: tasks fuer Teilsummen aus 10 Elementen,
--          tasks nach Bedarf rekursiv erzeugt und gestartet,
--          Ergebnis wandert zurueck durch Erzeugertasks
----------------------------------------------------------------------

with Stringpack; use Stringpack;
procedure Arbeitsteilung4 is

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

   type Worker_Ptr is access Worker;

   function Get_New_Worker return Worker_Ptr is --Hilfsfunktion, erzeugt neue task
   begin
      return new Worker;
   end Get_New_Worker;

   task body Worker is
      Local_From, Local_To: Integer;
      Local_Res, Remote_Res: Integer := 0;
      Colleague: Worker_Ptr;
   begin
      accept Start(From, To: Integer) do
         Local_From := From;
         Local_To := To;
      end Start;
      if Local_To-Local_From >10 then
         Colleague := Get_New_Worker; --task type cannot be used as type mark within its own body
         Colleague.Start(Local_From+10, Local_To);
         for I in Local_From..(Local_From+9) loop
            Local_Res := Local_Res+I;
         end loop;
         Colleague.Result(Remote_Res);
      else
         for I in Local_From..Local_To loop
            Local_Res := Local_Res+I;
         end loop;
      end if;
      accept Result(Res: out Integer) do
         Res := Local_Res+Remote_Res;
      end Result;
   end Worker;

   N, Sum: Integer;
   W: Worker_Ptr := new Worker;

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

