2012-03-05 8 views
1

gen_fsmタイムアウトに関する質問があります。たとえば、開始状態であるidleと、workingの2つの状態を持つgen_fsmのセットがあるとします。gen_fsm erlangタイムアウト

5秒間、gen_fsmは特定のパラメータをチェックし、それに応じてidleに留まるか、workingに移動します。 gen_fsmがworkingに移動するたびに、他のすべてのgen_fsmにメッセージ(gen_fsm:send_all_state_event/2を使用)が送信されます。の番号はworkingに、workingの番号は着信メッセージを無視してください。

ここで、状態のタイムアウトにスキューを持たせたくないという点があります(たとえば、マシンがworkingに3秒間入っていてメッセージを受信した場合はどうなりますか?5秒のタイムアウトはもはや有効ではなく、 (固定の時間にタイムアウトメッセージをトリガする必要があることを意味します)

now()time:now_diff/2を使用する私の解決策の顕著な部分は次のとおりです。私は小さなドリフトを持っていますとにかく、秒の数分を話してから公正だと思われます。

あなたはそれが妥当だと思いますか?

{ok, idle, #state{time = now()}, 5000}. 

idle(timeout, State) -> 
    %% do some operations 
    {next_state, idle, State#state{time = now()}, 5000}. 

working(timeout, State) -> 
    %% do some other actions 
    {next_state, working, State#state{time = now()}, 5000}. 

handle_event(work, working, #state{time = Time} = State) -> 
    Timeout = round(timer:now_diff(now(), Time)/1000), 
    {next_state, working, State, Timeout}. 

handle_event(work, StateName, state{time = Time} = State) -> 
    Timeout = round(timer:now_diff(now(), Time)/1000), 
    {next_state, working, State, Timeout}. 

答えて

4

timer:apply_intervalのいずれかを使用して、イベントをfsmに送信するapi関数を呼び出すことができます。

timer:send_intervalを使用して、gen_fsmのhandle_infoコールバックで処理できるカスタムメッセージを送信します。

+0

実際、私は各状態gen_fsm:send_event_after(5000、タイムアウト)でコードを変更しました。これはどう思いますか? – user601836

+0

これはIMHOの欠点を持っています。間違いをもう一度覚えてしまいます。一定の間隔を保つためには、常に現在の時刻を修正する必要があります。タイマー:* _ interval関数は、空き時間に正しく動作します。 –