2014-02-20 29 views
4

我的程序遇到了一些麻烦。在Ada中取消使用受保护对象的流程

我有一个进程调用一个函数(Take_Job),该函数在时间(MINIMUM_WAIT)通过之前应该保持阻塞状态。如果没有发生这种情况,将会出现一条通知这种情况的消息。

for Printer_Id in Type_Printer_Id loop 
    select 
     delay MINIMUM_WAIT 
     Pragma_Assert (True, ""); 
    then abort 
     Take_Job (Controller, 
        Printer_Id, 
        Max_Tonner, 
        Job, 
        Change_Tonner); 
     Pragma_Assert 
     (False, 
      "Testing of Take_Job hasn't been successful. It should have remained blocked."); 
    end select; 
end loop; 

功能Take_Job调用一个受保护对象的条目:

procedure Take_Job (R     : in out Controller_Type; 
         Printer  : in  Type_Printer_Id; 
         Siz   : in  Typo_Volume; 
         Job   : out Typo_Job; 
         Excep_Tonner : out Boolean) is 
begin 
    R.Take_Job(Printer, Siz, Job, Excep_Tonner); 
end Take_Job; 

其中 “R” 是保护对象。

以下代码是受保护对象的条目。实际上,“when”条件为真,因为我需要使用条目的参数来检查某些东西。由于Ada不允许我这样做,因此我将受保护对象中的参数复制并调用“延迟的条目”,然后在“延迟的条目”中,我将确保在继续之前满足条件。

entry Take_Job(Printer_Id: in Type_Printer_Id; Remaining: in Type_Volume; Job: out Type_Job; exceptionTonner: out Boolean) 
when True is 
begin 
    Copy_Remaining(Printer_Id) := Remaining; 
    requeue Take_Job_Delayed(Printer_Id); 
end Take_Job; 

让我们来看看“延迟进入”代码:

entry Take_Job_Delayed(for J in Type_Printer_Id)(Printer_Id: in Type_Printer_Id; Remaining: in Type_Volume; Job: out Type_Job; exceptionTonner: out Boolean) 
when False is -- I've done this on purpose 
begin 
    null; -- Actually, there would be a lot of code here 
end Take_Job_Delayed; 

比方说,我的目标是要通过MINIMUM_WAIT并运行“Pragma_Assert(没错,‘’)”。如果我把Take_Job的“when”条件设置为“False”,那么一切正常。 Take_Job永远不会被接受,并且Pragma_Assert将被执行。如果我将它设置为“True”,并且Take_Job_Delayed的“when”条件为“False”,我不会得到相同的效果,并且进程被阻止,Pragma_Asserts也不会执行。

为什么?看起来问题出现在“要求”或其附近,但为什么会发生这种情况?

回答

5

您需要执行请求with abort;

entry Take_Job(Printer_Id: in Type_Printer_Id; 
       Remaining: in Type_Volume; 
       Job: out Type_Job; 
       exceptionTonner: out Boolean) 
when True is 
begin 
    Copy_Remaining(Printer_Id) := Remaining; 
    requeue Take_Job_Delayed(Printer_Id) with abort; 
end Take_Job; 

因为否则机会中止输入呼叫已丢失。在ARM 9.5.4有详细资料,并且在Burns & Wellings,“Concurrency in Ada”中有一个更加可以理解的解释。

+0

你是对的。 – ArthurTheLearner