I have 3 processes labeled p0…p2. I want p0 to send to all processes(including itself) the message {:prepare, data_msg }
. p1 and p2 receive the message and compute the relevant steps. p0 shoots out the following error:
** (ArgumentError) errors were found at the given arguments:
* 1st argument: not an atom
:erlang.apply([prepare: {:msg, 1, 32, #PID<0.117.0>}, prepare: {:msg, 1, 32, #PID<0.117.0>}, prepare: {:msg, 1, 32, #PID<0.117.0>}], :a_bal, [])
algorithm.ex:51: Algorithm.run/1
I’m very unsure as to why this is happenig to only p0 as p0 is essentially running the same code as p1 and p2.
Here are the relevant code snippets:
defmodule Algorithm do
def start(name, participants, client) do
pid = spawn(Algorithm, :init, [name, participants, client])
# :global.unregister_name(name)
case :global.re_register_name(name, pid) do
:yes -> pid
:no -> :error
end
IO.puts "registered #{name}"
pid
end
def init(name, processes, client) do
Process.sleep(10)
state = %{
name: name,
processes: processes,
client: (if is_pid(client), do: client, else: self()),
bal: -1,
v: 0,
a_bal: nil,
a_val: nil,
}
run(state)
end
def run(state) do
state = receive do
{:propose, val} ->
b = 1
data_msg = {:msg, b, val, self()}
IO.puts(":propose | #{inspect state.name} | data_msg: #{inspect data_msg}")
IO.puts(":propose | #{inspect state.name} | state: #{inspect state}")
beb_broadcast({:prepare, data_msg}, state.processes)
{:prepare, data_msg} ->
{:msg, b, v, p} = data_msg
# update state with b
#{state | bal: b}
IO.puts(":prepare | #{inspect state.name} | data_msg: #{inspect data_msg}")
send(p, {:prepared, b, state.a_bal, state.a_val, data_msg})
{:prepared, b, a_bal, a_val, data_msg} ->
IO.puts(":prepared | #{inspect state.name} | b: #{inspect b}")
end
run(state)
end
defp unicast(m, p) do
case :global.whereis_name(p) do
pid when is_pid(pid) -> send(pid, m)
:undefined -> :ok
end
end
defp beb_broadcast(m, dest), do: for p <- dest, do: unicast(m, p)
end
This are the lines I ran in IEX to reproudce the error
c "algorithm.ex"
procs=[:p0, :p1, :p2]
pids = Enum.map(procs, fn(p) -> Algorithm.start(p, procs, self()) end)
[ x, y, z ] = pids
send(x, {:propose, 32})
Note: state.processes is a list containing all process names