Erlang:观察gen_server状态而不会打扰超时

时间:2015-10-26 08:08:22

标签: erlang

我有一个模仿gen_fsm的gen_server,(不要问我为什么......),gen_server:call会导致当前状态的gen_server转移到下一个状态,如果没有{{1}在一定时间内调用,gen_server终止。

更具体地说,gen_server的生命周期如下:

gen_server:call

当服务器处于state_i时,如果在此服务器上没有调用gen_server调用,则在t_i秒之后,服务器将进入状态终止,原因是,这是通过使用state_1 -> state_2 -> ... -> state_N -> terminated作为返回来实现的。 {reply, Reply, NewState, t_i}

该方法的问题在于,我无法从此gen_server中检索一些信息,为此,我需要调用gen_server:调用它,这会使超时混乱。

一种可能的解决方法是将最后一个状态传输时间戳放入状态,在每次检索调用之后,将新超时重置为适当的值,原型如下所示:

handle_call/3

通过这种方式,我可以得到我想要的效果,但它很难看,有没有更好的方法呢?

1 个答案:

答案 0 :(得分:2)

如果您想独立于其他事件(如来电)设置超时,则最好使用定时消息。

设置超时时使用erlang:send_after / 3:

TimerRef = erlang:send_after(10000, self(), my_timeout).

您可以随时使用erlang取消暂停:cancel_timer / 1。

erlang:cancel_timer(TimerRef).

使用handle_info接收它:

 handle_info(my_timeout, State) ->

如果你需要多个这样的超时,使用不同的消息,或者如果你有可能出现某种竞争条件并需要进一步控制,你可以用erlang创建唯一的引用:make_ref / 0并发送一条消息,如{Ref ,my_timeout}。

注意边缘情况 - 记住你可以取消一个计时器然后仍然意外地接收它(因为它取消时它在你的消息队列中),并且你没有使它们成为唯一的(如上所述使用参考)你可能会期待超时,并提前得到它,因为它是前一个进入你的消息队列等等(与参考一样,你可以检查它是最新的设置)。这些东西很容易处理,但请注意它们。