假设您使用第三方库来实现这一点(基本上是OTP
*:call/*
功能有):
call(Pid, Request) ->
call(Pid, Request, ?DEFAULT_TIMEOUT).
call(Pid, Request, Timeout) ->
MRef = erlang:monitor(process, Pid),
Pid ! {call, self(), MRef, Request},
receive
{answer, MRef, Result} ->
erlang:demonitor(Mref, [flush]),
{ok, Result};
{'DOWN', MRef, _, _, Info} ->
{error, Info}
after Timeout ->
erlang:demonitor(MRef, [flush]),
{error, timeout}
end.
然后在代码中使用它来监视同一进程
Pid
然后调用函数
call/2,3
.
my_fun1(Service) ->
MRef = erlang:monitor(process, Service),
ok = check_if_service_runs(MRef),
my_fun2(Service),
mind_my_stuf(),
ok = check_if_service_runs(MRef),
erlang:demonitor(MRef, [flush]),
return_some_result().
check_if_service_runs(MRef) ->
receive
{'DOWN', MRef, _, _, Info} -> {down, Info}
after 0 -> ok
end.
my_fun2(S) -> my_fun3(S).
% and a many layers of other stuff and modules
my_fun3(S) -> call(S, hello).
如果
erlang:monitor/2,3
将始终返回相同的引用,如果
erlang:demonitor/1,2
将删除以前的监视器。这将是一个丑陋和无法解决的错误的来源。您应该开始认为有库、其他进程,您的代码是大型系统的一部分,而Erlang是由有经验的人精心设计的。可维护性是这里的关键。