Ada 嵌套的;然后中止“;奇怪的行为

Ada 嵌套的;然后中止“;奇怪的行为,ada,Ada,嵌套的“then abort”结构在Ada中合法吗?如果是,我如何正确使用它们?我有以下代码: with Ada.Text_IO; use Ada.Text_IO; procedure Main is task TestTask is end TestTask; task body TestTask is begin select delay 2.0; Put_Line("C"); -- never executed then abo

嵌套的“then abort”结构在Ada中合法吗?如果是,我如何正确使用它们?我有以下代码:

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is

  task TestTask is
  end TestTask;

  task body TestTask is
  begin
    select
      delay 2.0;
      Put_Line("C"); -- never executed
    then abort
      select
        delay 5.0;
      then abort
        Put_Line("A");
        delay 4.0;
      end select;
      loop
        Put_Line("B");
        delay 10.0;
      end loop;
    end select;
  end TestTask;

begin
  null;
end Main;
我希望这段代码应该在2秒后退出。但是,它连续打印“B”,甚至没有延迟(它忽略
延迟10.0
)。看起来代码的行为方式如下:

  • 执行
    Put\u Line(“A”)
    并等待2秒钟
  • 退出内部“然后中止”
  • 执行循环忽略
    延迟10.0
  • 如果插入
    delay4.0
    而不是
    delay1.0
    (然后在循环中发生中止),程序将正常工作。我认为这是非常危险的,因为“abort then”可以在库函数中,例如:

    procedure Main is
    
      ----- It's function from library -----
    
      procedure Foo is
      begin
        select
          delay 5.0;
        then abort
          Put_Line("A");
          delay 4.0;
        end select;
      end;
    
      ---------------------------------------
    
      task TestTask is
      end TestTask;
    
      task body TestTask is
      begin
        select
          delay 2.0;
          Put_Line("C"); -- never executed
        then abort
          Foo;
          loop
            Put_Line("B");
            delay 10.0;
          end loop;
        end select;
      end TestTask;
    
    begin
      null;
    end Main;
    
    有人能解释一下为什么这个程序的行为如此怪异吗?

    如中所述,“异步select语句正确处理嵌套的ATC。例如,如果外部触发语句的延迟在内部延迟挂起时过期,则内部延迟将被取消,ATC将从内部可中止部分发布……”

    下面的变体按预期打印
    abbbc
    。外部触发语句指定5秒超时;嵌套触发语句指定3秒超时。由于后者的可中止部分仅消耗其每秒预算的1秒,因此随后的
    循环可以在外部时间之前打印4个Bt、 将外部
    延迟
    更改为
    1.0
    ,以再现示例中的效果

    with Ada.Text_IO; use Ada.Text_IO;
    
    procedure Main is
    
       task TestTask;
    
       task body TestTask is
       begin
          select
             delay 5.0;
             Put("C");
          then abort
             select
                delay 3.0;
             then abort
                Put("A");
                delay 1.0;
             end select;
             loop
                Put("B");
                delay 1.0;
             end loop;
          end select;
       end TestTask;
    
    begin
       null;
    end Main;