with Ada.Text_IO; use Ada.Text_IO;
with Id_Generator_Sequential;
procedure Synchronize_Task_Groups is
type Task_Range is new Positive range 1 .. 10;
package Id_Generator is new Id_Generator_Sequential (Task_Range);
use Id_Generator;
type Release_Type is (Release_Immediately, Wait_For_Trigger);
protected Synchronizer is
entry Synchronize_All_Tasks (Release : Release_Type);
entry Wait_For_All_Tasks;
procedure Trigger;
private
entry Wait_For_Trigger_Condition;
Release_Tasks,
Tasks_Complete,
Triggered : Boolean := False;
end Synchronizer;
protected body Synchronizer is
entry Synchronize_All_Tasks (Release : Release_Type) when Synchronize_All_Tasks'Count = Task_Range'Last or else Release_Tasks is
begin
Tasks_Complete := True;
Release_Tasks := Synchronize_All_Tasks'Count > 0;
case Release is
when Release_Immediately => null;
when Wait_For_Trigger => requeue Wait_For_Trigger_Condition with abort;
end case;
end Synchronize_All_Tasks;
entry Wait_For_All_Tasks when Tasks_Complete is
begin
Tasks_Complete := Wait_For_All_Tasks'Count > 0;
end Wait_For_All_Tasks;
procedure Trigger is
begin
Triggered := True;
end Trigger;
entry Wait_For_Trigger_Condition when Triggered is
begin
Triggered := Wait_For_Trigger_Condition'Count > 0;
end Wait_For_Trigger_Condition;
end Synchronizer;
task type Synchronized_Operations (Task_Id : Task_Range := Set_Id);
task body Synchronized_Operations is
begin
Put_Line ("Task" & Task_Range'Image (Task_Id) & " initialized");
delay Duration (Float (Task_Id));
Put_Line ("Task" & Task_Range'Image (Task_Id) & " waiting for others to check in and trigger before starting");
Synchronizer.Synchronize_All_Tasks (Wait_For_Trigger);
Put_Line ("Starting Task" & Task_Range'Image (Task_Id));
delay Duration (Float (Task_Id));
Put_Line ("Task" & Task_Range'Image (Task_Id) & " waiting for others to check in before terminating");
Synchronizer.Synchronize_All_Tasks (Release_Immediately);
Put_Line ("Stopping Task" & Task_Range'Image (Task_Id));
end Synchronized_Operations;
Tasks : array (Task_Range) of Synchronized_Operations;
begin
Synchronizer.Wait_For_All_Tasks;
Put_Line ("--- All tasks ready ---");
delay 3.0;
Synchronizer.Trigger;
Put_Line ("--- All tasks starting ---");
Synchronizer.Wait_For_All_Tasks;
Put_Line ("--- All tasks complete ---");
end Synchronize_Task_Groups;