2013-03-30 43 views
1

我一直在阅读关于ada中的任务http://en.wikibooks.org/wiki/Ada_Programming/Tasking,并认为我会自己写一些任务。由于我最近读了一个关于Pintos的小课程,我认为我会实现一些读者 - 作家算法。这是我在它的尝试: Ada任务和终止

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; 

可能是值得一提的是,我希望看到的行为是在没有操作(PUSH/POP)一直到队列/堆栈取得1秒我会就像终止/退出无限循环的任务一样。

但是,这只是输出“开始”,然后去我的延迟1.0和输出“等待”。这并不是我所期望的,因为我已经接受了至少推动,这是我第一次打电话。我在哪里思考错误,为什么不工作?还有,有没有更多的资料来源举例说明如何在Ada中完成任务?我设法通过在2个不同的任务中创建一个Semaphore和Lock来实现这一点,但这似乎是一个不好的解决方案,并不是非常漂亮。

+0

好看的小例子。我要做的第一件事是稍微改进诊断:让队列任务报告“推”,“爆裂”或“等待”,并报告您在问题中看到的内容。 –

+0

关注你的建议,谢谢!看起来,我的选择直接进入延迟,是因为延迟是第一件事情开始时,任务开始,然后它卡在那里等待接受我的电话退出? – lfxgroove

+0

你的假设看起来正确;将会有一个不同的select语句变体,它完全符合你的要求。我应该非正式地知道答案,因为我在空闲时间一直在阅读伯恩斯和威灵! –

回答

4

改进了诊断程序后,很明显在启动时,Select替代品都不能立即使用,因此队列任务直接进入Else部分,并在1秒延迟后等待接受Quit

同时,主要任务是阻止了其第一(无条件的,不定时的!)Push入口调用,所以它不可能发出Quit入口调用。结果:死锁。

的溶液(第108页上在Burns & Welling描述)仅仅是改变ELSEOR使得第三(延迟)选项仍然是一个Select替代。然后在每次迭代中,(Push,Pop或Delay)中最早的一个将被接受。

+0

再次感谢!真的很高兴的帮助! – lfxgroove

+0

没错。认识到选择语句分支上的警卫只在选择语句的顶部进行评估是很重要的。如果一名守卫在等待时变得开放,那么选择语句将不会看到守卫,直到你绕着循环再次执行。 –