Ada select 多个条目

Ada select multiple entries

我正在寻找对多个条目进行 select 的方法。我有以下任务和 select 块。目的是在其他地方 运行 多 (2) 个任务,运行 直到一个完成,或者在一段时间后超时

task type t_startup_task is
   entry start;
   entry started;
end t_startup_task;

task body t_startup_task is
   startup_sig : Boolean := False;
begin
   accept start;
   busy : loop -- wait for external flag to become true
      status.read_signal (startup_sig);
      if startup_sig then
         exit busy;
      end if;
      delay 0.1;
   end loop busy;
   accept started;
end t_startup_task;

<...>

startup_task.start;
select
   startup_task.started;
or
   state.wait_done; -- other entry
   abort startup_task;
   return False;
or
   delay 4.0;
end select;

但是,这会导致以下编译错误:

only allowed alternative in timed entry call is delay
"or" not allowed here

实际执行此操作的最佳方法是什么?

遗憾的是,您不能使用 select 语句来决定多个条目调用。但是,您可以使用它们来决定是否接受条目,因此具有三个任务的实现应该可以工作。

您仍然可以通过在最终入口调用中使用输出参数来获得您的 return 值。

task startup_task is
    entry start;
    entry wait_done;
    entry signalled;
    entry started (success : out boolean);
end startup_task;

-- This task waits upon your other entry, then calls the startup_task
-- entry once it has completed
task startup_wait is
    entry start;
end startup_wait;
task body startup_wait is
begin
    accept start;
    state.wait_done;
    startup_task.wait_done;
end startup_wait;

-- This task contains your busy loop and calls the startup_task
-- entry once it has completed
task startup_signal is
    entry start;
end startup_signal;
task body startup_signal is
begin
    accept start;
    busy : loop -- wait for external flag to become true
        status.read_signal (startup_sig);
        if startup_sig then
            exit busy;
        end if;
        delay 0.1;
    end loop busy;
    startup_task.signalled;
end startup_signal;

-- This task provides the functionality of your invalid select statement, 
task body startup_task is
    success : boolean := False;
begin
    -- These start signals ensure that the subtasks wait for synchronisation
    accept start;
    startup_wait.start;
    startup_signal.start;
    select
        accept signalled;
        abort startup_wait;
        success := True;
    or
        accept wait_done;
        abort startup_signal;
    or
        delay 4.0
        abort startup_wait;
        abort startup_signal;
    end select;
    accept started (success);
end startup_task;

<...>

result : boolean;
begin
    -- this block replaces your invalid select statement
    startup_task.start;
    startup_task.started(result);
    return result;
end;

请注意,我尚未测试或编译此代码,但它应该提供解决方案的思路。

从技术上讲,该语言允许这样做:

select
   delay 4.0;
   ...
then abort
   select
      Entry1;
      ...
   then abort
      Entry2;
      ...
   end select;
end select;

这可能会做你想做的事。然而,最好的方法可能是让任务检查受保护的对象,并等待 PO 的条目:

protected Multi_Wait is
   procedure Task1_Ready;
   procedure Task2_Ready;
   entry Wait_For_Either (Task_1 : out Boolean; Task_2 : out Boolean);
private -- Multi_Wait
   Task1 : Boolean := False;
   Task2 : Boolean := False;
end Multi_Wait;

那么你的代码就可以做到

select
   Multi_Wait.Wait_For_Either (Task_1 => Task_1, Task_2 => Task_2);

   if not Task_1 and Task_2 then
      abort T1;

      return False;
   end if;
or
   delay 4.0;
end select;

您的任务会调用适当的过程,而不是等待第二次入口调用。