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

Mar*_*ner 2 concurrency multithreading scope ada task

我当时正在编写一些多线程 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;
Run Code Online (Sandbox Code Playgroud)

期望任务一旦接受条目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
Run Code Online (Sandbox Code Playgroud)

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

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

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

Nik*_*sti 5

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

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

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