Ada - 带延迟语句的控制异步传输不会中止(使用GNAT)

时间:2014-10-06 23:32:40

标签: delay ada abort gnat

简介

我遇到了异步控制转移的不错的Ada功能,但不知何故,参考手册和示例应用程序并不适合。

以下示例写在Reference Manual 9.7.4

select
  delay 5.0;
  Put_Line("Calculation does not converge");
then abort
  -- This calculation should finish in 5.0 seconds;
  --  if not, it is assumed to diverge.
  Horribly_Complicated_Recursive_Function(X, Y);
end select;

我现在以下列方式重建并运行它(完整文件):

with Ada.Text_IO; use Ada.Text_IO;
procedure asynch_transf_ex is
begin
  Put_Line("Before Select");
  select
    delay 1.0;
    -- will never be printed
    Put_Line("1 Second is over");
  then abort
    loop
      null;
    end loop;
  end select;
  -- again, not printed
  Put_Line("After Select");
end asynch_transf_ex;

(编译:gnatmake -gnat2012 -gnata -ggdb -O0 asynch_transf_ex.adb)

问题

正如评论中所注意到的,循环永远运行并且不会中断。相比之下,参考手册指出,它应该在(大约)1秒后中断。

现在,有些情况下,中止地区的陈述可以安全地免于中止,如RM第9.8节所述:

  • 受保护的行动;
  • 等待一个入境通话完成(在开始尝试取消它之后 - 见下文);
  • 等待依赖任务的终止;
  • 执行Initialize过程作为受控对象的默认初始化的最后一步;
  • 执行Finalize程序,作为受控对象的最终确定的一部分;
  • 对具有受控部分的对象的赋值操作。

但循环应该不是它们 - 实际上,如果我用null;替换delay 0.0;,那么执行将按预期运行。

在示例中提到了递归函数,我还想到函数调用在某种程度上是在时间结束后中止执行的触发器。但是,通过调用过程null;替换procedure do_null is begin null; end;并没有改变任何内容。 (我看了一下objdump - 电话没有被调整掉。)

阅读this explanation about GNAT's implementation of these constructs并没有帮助我。

问题

那么,我是否会错过参考手册中的一点,或者这只是GNAT的一个问题?如果是这样,delay 0.0;是否适合" Hotfix",还是有更好的解决方案?

感谢您的帮助。

修改

我正在运行Linux(uname -r = 3.16.3-1-ARCH--来自Arch Linux-repos的标准内核,未修改),并且(如已提到信号,可能处理器类型很有趣,在英特尔(R)酷睿(TM)i5-4570 CPU @ 3.20GHz和英特尔奔腾987上尝试过它。

1 个答案:

答案 0 :(得分:3)

虽然您引用的部分列出了可能不会发生中止的位置,即中止延迟操作,但如果不是,则不会立即发生中止 在中止延期的操作中。事实上,在9.8马币中,还有一个中止完成点列表

  

除了这些直接的情况,执行构造   中止之前并不一定完成   abort_statement完成。但是,执行中止   构造完成不迟于其下一个中止完成点(如果   任何)在中止延期操作之外发生的;下列   是执行的中止完成点:

     
      
  • 执行启动另一个任务的激活点;

  •   
  • 任务激活结束;

  •   
  • 执行条目调用,accept_statement,delay_statement或abort_statement的开始或结束;

  •   
  • 执行select_statement或者exception_handler的sequence_of_statements的开始。

  •   

因此,如果一系列语句被中止,则在下一个语句发生之前不必发生中止。示例中的循环不会执行任何会导致中止完成点的循环;因此,仅使用9.8中的规则,中止永远不会发生。添加delay 0.0;将提供中止完成点。

如果支持实时附件,则RM D.6(“抢先中止”)表示如果不是在中止延迟操作中,则必须立即在单处理器系统上发生中止。但是,附件D是可选的,并非所有实现都支持它。

如果您在Windows上运行,那么我认为不支持附件D,我认为不支持抢先中止,因为Windows没有提供一种安全的方法来立即终止线程而没有线程的合作。

GNAT支持在Windows上使用Polling pragma;这会生成代码,检查另一个线程是否已尝试中止当前线程。