是否可以向 elixir/erlang 中的所有子进程发送消息?

Is it possible to send a message to all child processes in elixir/erlang?

假设我在 elixir 中生成多个子进程。

defmodule Child do
  def start(name) do
    receive do
      msg -> IO.puts "Message received by #{name}: #{inspect msg}"
    end
  end
end

defmodule Parent do
  def main do
    child1 = spawn_link (fn -> Child.start("1") end)
    child2 = spawn_link (fn -> Child.start("2") end)
    child3 = spawn_link (fn -> Child.start("3") end)
  end
end

我是否可以向当前进程(或其他进程)的 所有 子进程发送消息?

send_to_children self(), "hello to all children"

例如,我可以通过某种方式告诉运行时向链接到当前进程的所有进程广播消息?我当然可以将所有生成的 pid 存储在某种数据结构中并循环执行此操作,但如果有某种规范的方法来执行此操作,它似乎会更有效且更不容易出错。

由于您使用的是 spawn_link,您可以获取所有链接进程的列表并向它们发送消息:

defmodule Child do
  def start(name) do
    receive do
      msg -> IO.puts "Message received by #{name}: #{inspect msg}"
    end
  end
end

defmodule Parent do
  def main do
    child1 = spawn_link (fn -> Child.start("1") end)
    child2 = spawn_link (fn -> Child.start("2") end)
    child3 = spawn_link (fn -> Child.start("3") end)
    {:links, links} = Process.info(self, :links)
    for pid <- links do
      send pid, :foo
    end
  end
end

Parent.main
:timer.sleep(1000)

输出:

Message received by 2: :foo
Message received by 1: :foo
Message received by 3: :foo

我认为直接获取一个进程的子进程列表是不可能的:http://erlang.org/pipermail/erlang-questions/2013-April/073125.html。如果您从 Supervisor 生成它们,则有一些方法,但不是针对任意情况。

你看过 PubSub 吗?唯一的限制是你所有的进程都将被命名为相同的 https://hexdocs.pm/elixir/master/Registry.html#module-using-as-a-pubsub

{:ok, _} = Registry.start_link(:duplicate, Registry.PubSubTest)

# process 1
{:ok, _} = Registry.register(Registry.PubSubTest, "room_1", [])

# process 2
{:ok, _} = Registry.regiser(Registry.PubSubTest, "room_1", [])

Registry.dispatch(Registry.PubSubTest, "room_1", fn entries ->
 for {pid, _} <- entries, do: send(pid, {:broadcast, "world"})
end)
#=> :ok