link 工艺环不对称
link asymmetry in process ring
我目前正在研究 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" => [#PID<0.120.0>, #PID<0.122.0>], "pid" => #PID<0.121.0>},
%{"links" => [#PID<0.121.0>], "pid" => #PID<0.120.0>}]
我注意到这里的链接不对称 - #PID<0.120.0>
应该有映射 "links" => [#PID<0.121.0>,#PID<0.122.0>]
而不仅仅是 "links" => [#PID<0.121.0>]
吗?
代码如下:
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
这是因为您在收集其 :links
的同时 link 处理进程,但正在为该进程创建一些 link 在你收集它的link之后。
例如,如果您生成一个进程 a
,然后收集它的 link,它将是一个空列表。
iex(1)> a = spawn(fn -> :timer.sleep(:infinity) end)
#PID<0.82.0>
iex(2)> Process.info(a, :links)
{:links, []}
如果你现在生成 b
并且 link 它到 a
,b
将在其 link 中有 [a]
和 a
将有 [b]
.
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>]}
因此,如果您想要每个进程的最终 links,则需要在所有 linking 完成后为每个进程收集 links。
我目前正在研究 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" => [#PID<0.120.0>, #PID<0.122.0>], "pid" => #PID<0.121.0>},
%{"links" => [#PID<0.121.0>], "pid" => #PID<0.120.0>}]
我注意到这里的链接不对称 - #PID<0.120.0>
应该有映射 "links" => [#PID<0.121.0>,#PID<0.122.0>]
而不仅仅是 "links" => [#PID<0.121.0>]
吗?
代码如下:
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
这是因为您在收集其 :links
的同时 link 处理进程,但正在为该进程创建一些 link 在你收集它的link之后。
例如,如果您生成一个进程 a
,然后收集它的 link,它将是一个空列表。
iex(1)> a = spawn(fn -> :timer.sleep(:infinity) end)
#PID<0.82.0>
iex(2)> Process.info(a, :links)
{:links, []}
如果你现在生成 b
并且 link 它到 a
,b
将在其 link 中有 [a]
和 a
将有 [b]
.
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>]}
因此,如果您想要每个进程的最终 links,则需要在所有 linking 完成后为每个进程收集 links。