父线程何时与具有非全局范围的 ada 任务类型变量同步?

When does the parent thread synchronize with an ada task type variable with a non-global scope?

我正在研究一些多线程 Ada 网络代码,其中涉及并行接受和处理多个连接。使用 Ada 任务的理想情况,不是吗?具体来说,多个任务类型变量,循环启动。

好吧,我做了这样的事情:

with Ada.Text_IO;
use Ada.Text_IO;

Procedure foo is
   task type handler is
      entry Start(I: Integer);
   end handler;
   
   task body handler is
      task_index: Integer;
   begin
      accept Start(I: Integer) do
         task_index:=I;
      end Start;
      for I in 1..5 loop
         Put_Line("Task "&task_index'Image&": "&I'Image);
      end loop;
   end handler;

begin -- foo

   for t in 1..5 loop
      declare
         bar: handler;
      begin
         bar.Start(t);
      end;
   end loop;
end foo;

期望任务在接受 start 条目后将并行执行。 但是,如本例,主任务依次等待各个任务执行完毕:

$ gnat make foo
$ ./foo
Task  1:  1
Task  1:  2
Task  1:  3
Task  1:  4
Task  1:  5
Task  2:  1
Task  2:  2
Task  2:  3
Task  2:  4
Task  2:  5
Task  3:  1
Task  3:  2
Task  3:  3
Task  3:  4
Task  3:  5
Task  4:  1
Task  4:  2
Task  4:  3
Task  4:  4
Task  4:  5
Task  5:  1
Task  5:  2
Task  5:  3
Task  5:  4
Task  5:  5

预先声明所有任务,在一个数组中解决了这个问题,但让我很好奇这实际上是如何工作的,为什么,以及在哪里记录。

ARM2012 第 9.2 节第 6/3 段在我看来是说主线程在执行结束时等待它的子任务完成,但实际上它似乎在任务离开当前范围之前等待继续执行(即循环并开始下一个任务)。

这是编译器问题、文档问题还是编码问题?

该程序(两个版本)均按照 Ada 标准所述运行。在您显示的版本中,在 declare .. begin .. end 块中本地声明的任务对象 bar 取决于该块(它是任务的“主”),因此该块语句等待任务在执行继续之前终止(离开块语句)。

RM 的第 9.3 节“任务依赖性 - 任务终止”http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-9-3.html 部分定义了这一点,它显示了一个与您的代码接近的示例。我认为第 9.2 节中的第 6/3 段不相关 - 它描述了一些相当特殊的情况,在这些情况下,本地创建的任务永远不会被激活。

如您所见,解决方案是全局声明任务对象,以便“主人”寿命更长。 9.3 节中的示例显示了另一种使用访问类型和动态分配任务对象的解决方案。