When Task1
calls Task2.Part1Ready
, it blocks until Task2
issues accept Part1Ready
. Likewise, when Task2
calls Task1.Part1Ready
, it blocks until Task1
issues accept Part1Ready
.
This is known as a ‘deadly embrace', and means that neither task can proceed. One way round this is to use a protected object, perhaps like this:
protected Readiness is
procedure Task_1_Ready;
entry Wait_Until_Task_1_Ready;
procedure Task_2_Ready;
entry Wait_Until_Task_2_Ready;
private
Task_1_Is_Ready : Boolean := False;
Task_2_Is_Ready : Boolean := False;
end Readiness;
protected body Readiness is
procedure Task_1_Ready is
begin
Task_1_Is_Ready := True;
end Task_1_Ready;
entry Wait_Until_Task_1_Ready when Task_1_Is_Ready is
begin
null;
end Wait_Until_Task_1_Ready;
procedure Task_2_Ready is
begin
Task_2_Is_Ready := True;
end Task_2_Ready;
entry Wait_Until_Task_2_Ready when Task_2_Is_Ready is
begin
null;
end Wait_Until_Task_2_Ready;
end Readiness;
Then get rid of the Part1Ready
task entries, replacing
task body Task1Type is begin
Put_Line("Task1 Part1");
Task2.Part1Ready;
accept Part1Ready;
Put_Line("Task1 Part2”);
end;
with
task body Task1Type is begin
Put_Line("Task1 Part1");
Readiness.Task_1_Ready;
Readiness.Wait_Until_Task_2_Ready;
Put_Line("Task1 Part2”);
end;
and vice-versa in Task2Type
.