为什么可以在 Erlang 中创建对同一进程的多个监视器引用?
Why can you create multiple monitor references to the same process in Erlang?
这是一个跟踪示例,我可以在同一个 Pid 上调用 erlang:monitor/2
:
1> Loop = fun F() -> F() end.
#Fun<erl_eval.30.99386804>
2> Pid = spawn(Loop).
<0.71.0>
3> erlang:monitor(process, Pid).
#Ref<0.2485499597.1470627842.126937>
4> erlang:monitor(process, Pid).
#Ref<0.2485499597.1470627842.126942>
5> erlang:monitor(process, Pid).
#Ref<0.2485499597.1470627842.126947>
指令#4 和#5 编辑的表达式return 与#3 不同,这意味着可以在当前进程和Pid
之间创建多个监视器引用。是否存在您需要或使用对同一进程的多个监视器引用的实际案例?
我希望这与 return 相同的引用(return 一个新的可能意味着旧的有 failed/crashed),遵循相同的逻辑link/1
.
假设您使用执行此操作的第三方库(基本上是 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
总是 return 相同的引用并且 erlang:demonitor/1,2
会删除您以前的显示器,那将是多么令人讨厌的惊喜。这将是丑陋且无法解决的错误的来源。你应该开始思考有库,其他进程,你的代码是一个巨大系统的一部分,而 Erlang 是由有经验的人经过深思熟虑后制作的。可维护性是这里的关键。
这是一个跟踪示例,我可以在同一个 Pid 上调用 erlang:monitor/2
:
1> Loop = fun F() -> F() end.
#Fun<erl_eval.30.99386804>
2> Pid = spawn(Loop).
<0.71.0>
3> erlang:monitor(process, Pid).
#Ref<0.2485499597.1470627842.126937>
4> erlang:monitor(process, Pid).
#Ref<0.2485499597.1470627842.126942>
5> erlang:monitor(process, Pid).
#Ref<0.2485499597.1470627842.126947>
指令#4 和#5 编辑的表达式return 与#3 不同,这意味着可以在当前进程和Pid
之间创建多个监视器引用。是否存在您需要或使用对同一进程的多个监视器引用的实际案例?
我希望这与 return 相同的引用(return 一个新的可能意味着旧的有 failed/crashed),遵循相同的逻辑link/1
.
假设您使用执行此操作的第三方库(基本上是 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
总是 return 相同的引用并且 erlang:demonitor/1,2
会删除您以前的显示器,那将是多么令人讨厌的惊喜。这将是丑陋且无法解决的错误的来源。你应该开始思考有库,其他进程,你的代码是一个巨大系统的一部分,而 Erlang 是由有经验的人经过深思熟虑后制作的。可维护性是这里的关键。