我已经在http://en.wikibooks.org/wiki/Ada_Programming/Tasking阅读了一些关于ada任务的内容,并认为我会自己写一些关于任务的小事。自从我最近读了一篇关于Pintos的小课程后,我想我会实现一些读者编写算法。这是我的尝试:
procedure Test_Queue is
type Int_Array is array(1..10) of Integer;
task type Queue is
entry Quit;
entry Pop(Elem : out Integer);
entry Push(Elem : in Integer);
end Queue;
task body Queue is
Elems_In_Queue : Integer := 0;
Q : Int_Array;
begin
loop
select
accept Push(Elem : in Integer) do
Put_Line("Push");
Elems_In_Queue := Elems_In_Queue + 1;
Q(Elems_In_Queue) := Elem;
end Push;
or
when Elems_In_Queue > 0 =>
accept Pop(Elem : out Integer) do
Put_Line("Pop");
Elem := Q(Elems_In_Queue);
Elems_In_Queue := Elems_In_Queue - 1;
end Pop;
else
delay 1.0;
Put_Line("Waited");
accept Quit;
exit;
end select;
end loop;
Put_Line("Got out of the loop");
end Queue;
Q : Queue;
X : Integer;
begin
Put_Line("Started");
Q.Push(10);
Put_Line("Pushed");
Q.Push(11);
Put_Line("Pushed");
Q.Pop(X);
Put_Line("Integer:" & Integer'Image(X));
Q.Quit;
Put_Line("Done");
end Test_Queue;
值得一提的是,我希望看到的行为是,当没有对队列/堆栈进行操作(推/弹)1秒钟时,我希望任务终止/退出无限循环。 / p>
但这只是输出“已启动”然后转到我的延迟1.0并输出“等待”。这不完全是我的预期,因为我至少接受了推,这是我打电话的第一件事。我在哪里想错了,为什么这不起作用?另外,还有更多的资料来源,如何在Ada中进行任务分配?我设法通过在2个不同的任务中创建一个Semaphore和Lock来实现这一点,但这似乎是一个糟糕的解决方案而不是非常adaesque。
答案 0 :(得分:4)
改进了诊断后,很明显在启动时,Select
替代方案都没有立即可用,因此队列任务直接进入Else
部分,延迟1秒后等待接受Quit
。
与此同时,主要任务是阻止其第一次(无条件,不定时!)Push
条目调用,以便它永远不会发出Quit
条目调用。结果:死锁。
解决方案(第08页Burns & Welling中所述)只是将ELSE
更改为OR
,以便第三个(延迟)选项仍然是Select
替代选项。然后在每次迭代中,最早的(推,弹或延迟)将被接受。