У меня есть задача 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), и программа работает просто отлично, даже в нетривиальном примере, с которым я играл вчера вечером.
Этот обходной путь кажется таким простым, что я не понимаю, почему компилятор вообще должен выдавать первую ошибку! Я полагаю, что я должен был атаковать эту проблему совершенно неправильно. Считается ли это хорошей техникой Ады, и если нет, то каким будет Ада-подобный способ делать подобные вещи?