发送消息时确保gen_fsm / gen_server进程存在

时间:2013-07-23 16:14:21

标签: erlang otp message-passing gen-server gen-fsm

在Erlang中,建议在向其发送消息/事件之前确保某些进程存在的最佳方法是什么?在我的场景中,我在第一次出现消息时启动进程,然后它保持活动状态。在继续传递更多消息的同时,我首先尝试使用相同的名称启动该进程以确保它已启动,如下所示(使用gen_fsmsimple-one-for-one重启方案):

%% DeviceId - process name

heartbeat(ApplicationKey, DeviceId, Timeout) ->
    ensure_session_started(ApplicationKey, DeviceId, Timeout),
    gen_fsm:send_event(DeviceId, {heartbeat, Timeout}).

ensure_session_started(ApplicationKey, DeviceId, Timeout) ->
    case session_server_sup:start_child(ApplicationKey, DeviceId, Timeout) of
        {ok, _Pid} -> {ok, running};
        {error, {already_started, _}} -> {ok, running};
        {error, Error} -> erlang:throw({error, {failed_to_start_session, Error}})
    end.

我认为这个解决方案并不完美,并且可能有一些开销,但仍然相信它比使用erlang:is_process_alive更不容易出现竞争条件。我对吗?任何想法如何改进它?

2 个答案:

答案 0 :(得分:4)

你是对的,erlang:is_process_alive / 1方法在这种情况下由于竞争条件而无用。

你的例子是可行的,我在野外看了几次。请注意,它不保证将处理消息。为了确保您需要监控您的接收器并从中获得确认。这是在gen_server中完成的:call / 2。

答案 1 :(得分:2)

使用gen_fsm:sync_send_event/2,3,您可以向FSM发送事件并等待回复。因此,您可以告诉您的呼叫流程已收到其消息。