-- -- Uwe R. Zimmer, Australia, September 2011 -- -- with Ada.Task_Identification; use Ada.Task_Identification; with Ada.Text_IO; use Ada.Text_IO; procedure Link_Tasks is -- Structures to declare tasks in arrays of distinct ranges type Task_Range is mod 5; type Messages is new Natural; -- Required task declarations for different forms of linking tasks task type Task_Linked_By_Global_Array is entry Link_To (This_Task, Next_Task : Task_Range); -- assumes access to a global array of tasks entry Synchronous_Message (Message : Messages); -- just for illustration end Task_Linked_By_Global_Array; type Task_Linked_By_Reference; -- incomplete declaration so that we can use a reference to itself in its actual declaration below type Task_Linked_By_Reference_P is access all Task_Linked_By_Reference; task type Task_Linked_By_Reference is entry Link_To (This_Task : Task_Range; Next_Task : Task_Linked_By_Reference_P); -- tasks can now be allocated anywhere and individually entry Synchronous_Message (Message : Messages); -- just for illustration end Task_Linked_By_Reference; -- Declaring arrays of all task types Tasks_Linked_By_Global_Array : array (Task_Range) of Task_Linked_By_Global_Array; Tasks_Linked_By_Reference : array (Task_Range) of aliased Task_Linked_By_Reference; -- Task bodies for all of the above task body Task_Linked_By_Global_Array is This_Task_Ix, Next_Task_Ix : Task_Range; begin accept Link_To (This_Task, Next_Task : Task_Range) do This_Task_Ix := This_Task; Next_Task_Ix := Next_Task; end Link_To; declare The_Last_Word : Messages := Messages (Task_Range'First); procedure Send_Word (Word : in out Messages) is begin Word := Word + Messages (This_Task_Ix); Put_Line ("Task " & Task_Range'Image (This_Task_Ix) & " sends (index) :" & Messages'Image (Word)); Tasks_Linked_By_Global_Array (Next_Task_Ix).Synchronous_Message (Word); end Send_Word; begin if This_Task_Ix = Task_Range'First then Send_Word (The_Last_Word); accept Synchronous_Message (Message : Messages) do The_Last_Word := Message; end Synchronous_Message; Put_Line ("Task " & Task_Range'Image (This_Task_Ix) & " received (index) :" & Messages'Image (The_Last_Word)); else accept Synchronous_Message (Message : Messages) do The_Last_Word := Message; end Synchronous_Message; Put_Line ("Task " & Task_Range'Image (This_Task_Ix) & " received (index) :" & Messages'Image (The_Last_Word)); Send_Word (The_Last_Word); end if; end; end Task_Linked_By_Global_Array; -- task body Task_Linked_By_Reference is This_Task_Ix : Task_Range; Next_Task_P : Task_Linked_By_Reference_P; begin accept Link_To (This_Task : Task_Range; Next_Task : Task_Linked_By_Reference_P) do This_Task_Ix := This_Task; Next_Task_P := Next_Task; end Link_To; declare The_Last_Word : Messages := Messages (Task_Range'First); procedure Send_Word (Word : in out Messages) is begin Word := Word + Messages (This_Task_Ix); Put_Line ("Task " & Task_Range'Image (This_Task_Ix) & " sends (reference) :" & Messages'Image (Word)); Next_Task_P.all.Synchronous_Message (Word); end Send_Word; begin if This_Task_Ix = Task_Range'First then Send_Word (The_Last_Word); accept Synchronous_Message (Message : Messages) do The_Last_Word := Message; end Synchronous_Message; Put_Line ("Task " & Task_Range'Image (This_Task_Ix) & " received (reference) :" & Messages'Image (The_Last_Word)); else accept Synchronous_Message (Message : Messages) do The_Last_Word := Message; end Synchronous_Message; Put_Line ("Task " & Task_Range'Image (This_Task_Ix) & " received (reference) :" & Messages'Image (The_Last_Word)); Send_Word (The_Last_Word); end if; end; end Task_Linked_By_Reference; -- begin -- Linking up the tasks in a ring topology: for Task_Ix in Tasks_Linked_By_Global_Array'Range loop Tasks_Linked_By_Global_Array (Task_Ix).Link_To (Task_Ix, Task_Ix + 1); end loop; for Task_Ix in Tasks_Linked_By_Reference'Range loop Tasks_Linked_By_Reference (Task_Ix).Link_To (Task_Ix, Tasks_Linked_By_Reference (Task_Ix + 1)'Access); end loop; end Link_Tasks;