Domanda

So i've got code like this:

task body Task1Type is
begin
    Put_Line("Task1 Part1");
    Task2.Part1Ready;
    accept Part1Ready;
    Put_Line("Task1 Part2");
end;

task body Task2Type is
begin
    Put_Line("Task2 Part1");
    Task1.Part1Ready;
    accept Part1Ready;
    Put_Line("Task2 Part2");
end;

My logic tells me that part2 in every task must run after both tasks completed task1. But it doesn't. Where I'm wrong?

È stato utile?

Soluzione

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top