在Ada中中止使用重新排列的受保护对象的进程

时间:2014-02-20 12:19:44

标签: concurrency task ada protected-resource

我的节目遇到了一些麻烦。

我有一个进程调用一个函数(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”条件为True,因为我需要使用条目的参数检查一些内容。由于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(True,”“)”。如果我将Take_Job的“when”条件设置为“False”,那么一切正常。永远不会接受Take_Job,并且将执行Pragma_Assert。如果我将其设置为“True”并将Take_Job_Delayed的“when”条件设置为“False”,则不会产生相同的效果,并且进程将被阻止,并且不会执行任何Pragma_Asserts。

为什么呢?看起来这个问题出现在“重新排队”或者附近的某个地方,但为什么会这样呢?

1 个答案:

答案 0 :(得分: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& amp;中有一个更容易理解的解释。 Wellings,“Concurrency in Ada”