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}.
実際、私は各状態gen_fsm:send_event_after(5000、タイムアウト)でコードを変更しました。これはどう思いますか? – user601836
これはIMHOの欠点を持っています。間違いをもう一度覚えてしまいます。一定の間隔を保つためには、常に現在の時刻を修正する必要があります。タイマー:* _ interval関数は、空き時間に正しく動作します。 –