Ada: тип задачи как метка задачи в собственном теле - PullRequest
0 голосов
/ 08 мая 2018

У меня есть задача Ada, Do_Something, которая должна сама "вызываться". Я думаю, что это происходит из C ++, у меня есть поток, выполняющий void Do_Something(), и иногда void Do_Something() нужно порождать больше потоков, которые также запускают void Do_Something().

Аде (которую я изучаю) это не нравится. Кажется, это М (не) МЫ:

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;

затем измените оператор if в теле A_Task на следующее:

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

Эта последняя версия проходит GNAT (теперь у нас M *** W *** E), и программа работает просто отлично, даже в нетривиальном примере, с которым я играл вчера вечером.

Этот обходной путь кажется таким простым, что я не понимаю, почему компилятор вообще должен выдавать первую ошибку! Я полагаю, что я должен был атаковать эту проблему совершенно неправильно. Считается ли это хорошей техникой Ады, и если нет, то каким будет Ада-подобный способ делать подобные вещи?

1 Ответ

0 голосов
/ 08 мая 2018

Это поведение указано в RM 8,6 (17/3) : «Если имя использования появляется внутри декларативной области type_declaration и обозначает то же самое type_declaration, то оно обозначает текущий экземпляр типа (а не сам тип);»

Это означает, что фактическое имя типа нельзя использовать для создания экземпляра другого объекта. Обертка (как ваша) будет одним из способов сделать это. Подтип также должен работать subtype Foo is A_Task;

Имейте в виду, однако, что способ мышления / действия C ++ редко является способом выполнения действий Ada

...