Process 过程环中的链路不对称
我目前正在使用elixir中无处不在的流程环。 环是链接的,但采用以下方式:Process 过程环中的链路不对称,process,elixir,otp,symmetry,Process,Elixir,Otp,Symmetry,我目前正在使用elixir中无处不在的流程环。 环是链接的,但采用以下方式: iex(1)> Ring.Worker.create_ring_of_linked_processes(3) Ring.Worker.create_ring_of_linked_processes(3) [%{"links" => [#PID<0.121.0>, #PID<0.120.0>], "pid" => #PID<0.122.0>}, %{"links"
iex(1)> Ring.Worker.create_ring_of_linked_processes(3)
Ring.Worker.create_ring_of_linked_processes(3)
[%{"links" => [#PID<0.121.0>, #PID<0.120.0>], "pid" => #PID<0.122.0>},
%{"links" => [#PID<0.120.0>, #PID<0.122.0>], "pid" => #PID<0.121.0>},
%{"links" => [#PID<0.121.0>], "pid" => #PID<0.120.0>}]
iex(1)>Ring.Worker.创建链接进程的环(3)
创建链接进程的环(3)
[%{“links”=>[#PID,#PID],“PID”=>#PID},
%{“links”=>[#PID,#PID],“PID”=>#PID},
%{“links”=>[#PID],“PID”=>#PID}]
我注意到这里的链接有一个不对称性-#PID
应该有映射“links”=>[#PID,#PID]
而不仅仅是“links”=>[#PID]
代码如下:
def loop() do
receive do
{:link, pid} when is_pid(pid) ->
Process.link(pid)
loop()
end
end
def create_ring_of_linked_processes(num_of_processes) do
num_of_processes
|> create_processes
|> link_processes([])
end
def link_processes([pid1, pid2 | rest], linked_processes) do
send(pid1, {:link, pid2})
:timer.sleep(1)
{:links, links} = Process.info(pid1, :links)
link_processes(
[pid2 | rest], [%{"pid" => pid1, "links" => links} | linked_processes]
)
end
def link_processes([pid | []], linked_processes) do
%{"pid" => first_pid, "links" => _} = List.last(linked_processes)
send(pid, {:link, first_pid})
:timer.sleep(1)
{:links, links} = Process.info(pid, :links)
[%{"pid" => pid, "links" => links} | linked_processes]
end
@spec create_processes(integer) :: [pid]
def create_processes(num_of_processes) do
for _ <- 1..num_of_processes, do: spawn(__MODULE__, :loop, [])
end
def loop()do
接收do
{:link,pid}什么时候是_-pid(pid)->
进程链接(pid)
循环()
结束
结束
def创建链接进程的数量(进程的数量)do
进程数
|>创建流程
|>链接进程([]))
结束
def链接_进程([pid1,pid2 | rest],链接_进程)do
发送(pid1,{:链接,pid2})
:计时器。睡眠(1)
{:links,links}=Process.info(pid1,:links)
链接进程(
[pid2 | rest],%{“pid”=>pid1,“links”=>links}链接的|进程]
)
结束
def link_进程([pid |[]),linked_进程)do
%{“pid”=>first\u pid,“links”=>\u}=List.last(链接的\u进程)
发送(pid,{:链接,第一个\ pid})
:计时器。睡眠(1)
{:links,links}=Process.info(pid,:links)
[%{“pid”=>pid,“links”=>links}|链接的_进程]
结束
@规范创建_进程(整数):[pid]
def创建_进程(_进程的数量)do
对于{up>,这是因为您在收集流程的:链接的同时链接了流程,但该流程的某些链接是在收集其链接后创建的
例如,如果生成一个进程a
,然后收集它的链接,它将是一个空列表
iex(1)> a = spawn(fn -> :timer.sleep(:infinity) end)
#PID<0.82.0>
iex(2)> Process.info(a, :links)
{:links, []}
因此,如果您想要每个流程的最终链接,您需要在所有链接完成后收集每个流程的链接。您可以发布一个链接吗?如果您从Process.info(pid,:links)
获取链接,那么您可能调用它太早了。如果使用process.link/1
@Dogbert-sure,updated链接进程,则链接应对称。我使用了一毫秒的延迟。我想在所有的Process.link/1
调用完成后,您需要修改此设置以收集Process.info(,:links)
。@Dogbert产生对称性,谢谢!请您将其作为一个答案提交,并说明为什么这样做有效,而上述内容无效?通过使用Process.info(,:links)检查链接,我得到了对称的链接以进行报告
在create\u ring\u of \u linked\u processs/1
函数中执行link\u processs/2
函数后-但我不认为这保证了“链接是完整的”-在elixir中有什么方法知道这一点吗?即使执行了send(pid,{:link,{})
,loop/0
进程仍然需要在未知的时间内接收和处理消息。你是对的,这不是保证。通常的做法是让接收者在链接完成后向调用者发送另一条消息。呼叫方需要等待消息到达后才能继续GenServer.call
是一个健壮的实现,与我刚才描述的非常相似;如果您打算在实际应用程序中使用它,您可能希望将您的流程转换为GenServer
。很好,谢谢,可以-标记为答案,因为这只是一个没有保证链接报告对称性的示例。
iex(3)> b = spawn(fn -> Process.link(a); :timer.sleep(:infinity) end)
#PID<0.85.0>
iex(4)> Process.info(b, :links)
{:links, [#PID<0.82.0>]}
iex(5)> Process.info(a, :links)
{:links, [#PID<0.85.0>]}