2017-09-07 17 views
1

複数のエントリーを選択する方法を探しています。私は次のタスクを持ってブロックを選択しました。複数のエントリーを選択

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

何:意図は、これは以下のコンパイルエラーになり、

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; 

しかしある程度の時間の後に、別の場所で複数の(2)タスクを実行する1が完了するまで実行、またはタイムアウトすることです実際にこれを行う最善の方法?

答えて

3

残念ながら、複数のエントリ呼び出しの間には、selectステートメントを使用することはできません。ただし、これらを使用してエントリを受け入れるかどうかを決めることができます。したがって、3つのタスクを持つ実装が機能するはずです。

最後のエントリ呼び出しでoutパラメータを使用することで、戻り値を引き続き取得できます。

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; 

注:私はこのコードをテストしたりコンパイルしたりしていませんが、解決策に向かって考えてください。

0

技術的には、言語はこれを可能にする:

あなたが欲しいものを行う可能性があります
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; 

を行うことができます2回目の通話を待つ代わりに、適切な手順を実行します。