У меня вопрос по тайм-ауту gen_fsm. Допустим, у вас есть набор gen_fsm с двумя состояниями (в будущем может быть больше): idle
, которое является начальным состоянием, и working
.
Каждые 5 секунд gen_fsm проверит определенный параметр и в соответствии с ним останется в idle
или перейдет к working
. Всякий раз, когда gen_fsm переместится на working
, он отправит сообщение (используя gen_fsm:send_all_state_event/2
) всем другим gen_fsm: те, что в idle
, должны переместиться на 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}.