【问题标题】:gen_fsm erlang timeoutgen_fsm erlang 超时
【发布时间】:2012-03-22 21:03:17
【问题描述】:

我对 gen_fsm 超时有疑问。假设您有一组具有两种状态的 gen_fsm(将来可以更多):idle 是起始状态,working

gen_fsm 将在任何 5 秒内检查特定参数,并据此将保留在 idle 或移动到 working。每当一个 gen_fsm 移动到 working 时,它都会向所有其他 gen_fsm 发送一条消息(使用 gen_fsm:send_all_state_event/2):idle 中的那些应该移动到 workingworking 中的那个不应该关心传入的消息。

现在,关键是我不想在状态超时中出现偏差(例如,如果机器在 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}.

【问题讨论】:

    标签: erlang gen-fsm


    【解决方案1】:

    您可以使用timer:apply_interval 调用将事件发送到您的 fsm 的 api 函数。

    或者您使用 timer:send_interval 发送自定义消息,您可以在 gen_fsm 中的 handle_info 回调中处理该消息。

    【讨论】:

    • 事实上我改变了在每个状态下使用的代码 gen_fsm:send_event_after(5000, timeout)。你怎么看这个?
    • 这有缺点恕我直言,你会再次得到一些间隔的漂移。要保持固定的时间间隔,您总是需要更正当前时间。 timer:*_interval 函数可以免费正确执行此操作。
    猜你喜欢
    • 2011-08-31
    • 2015-05-24
    • 2011-03-31
    • 2021-08-12
    • 2012-03-16
    • 2011-01-20
    • 2014-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多