Ada:任务类型作为任务标记在自己的体内

Ada: Task type as task mark in its own body

我有一个 Ada 任务 Do_Something,需要 "invoke" 本身。我认为它来自 C++,我有一个线程 运行ning void Do_Something(),有时 void Do_Something() 需要产生更多的线程也 运行 void Do_Something()

Ada(我正在学习)不喜欢这样。这似乎是一个 M(非)WE:

task body A_Task is

  new_task: access A_Task;
  my_level: Natural;

begin

  accept Do_Something(level: in Natural) do
    my_level := level + 1;
  end Do_Something;

  if my_level < 4 then
    new_task := new A_Task;
    new_task.Do_Something(my_level);
  end if;

end A_Task;

GNAT至少不喜欢这样,在new_task.Do_Something(my_level);报错因为

task type cannot be used as type mark within its own spec or body

然而,通过在任务外添加这样的过程可以轻松规避此问题:

procedure Circumvent(level: Natural) is
    new_task: access A_Task;
begin
    new_task := new A_Task;
    new_task.Do_Something(level + 1);
end Circumvent;

然后将 A_Task 正文中的 if 语句修改为:

  if my_level < 4 then
    Circumvent(my_level);
  end if;

后一个版本通过了 GNAT(现在我们有一个 M***W***E)并且程序 运行 很好,即使在我昨晚玩的一个重要示例中也是如此.

这个变通方法看起来非常简单,我根本不明白为什么编译器会引发第一个错误!我想我一定是在以完全错误的方式解决这个问题。这被认为是好的 Ada 技术吗?如果不是,做这种事情的类似 Ada 的方法是什么?

此行为在 RM 8.6(17/3) 中指定: "If a usage name appears within the declarative region of a type_declaration and denotes that same type_declaration, then it denotes the current instance of the type (rather than the type itself);"

这意味着类型的实际名称不能用于实例化不同的对象。 一个包装器(像你的)将是一种方法。 子类型也应该工作 subtype Foo is A_Task;

不过请注意,thinking/doing 的 C++ 方式很少是 Ada 的做事方式