Process
Process follows the Actor model.
Spawn a process
Use spawn to create a new process, it will return a Process Identifier (PID):
defmodule Adder do
def add(a, b) do
IO.puts(a + b)
end
end
iex> pid = spawn(Adder, :add, [1, 1])
2
#PID<0.110.0>
Receiving and sending messages
Use send to send message to a process:
defmodule Foo do
def listen do
receive do
msg -> IO.puts("received #{msg}")
end
end
end
iex> pid = spawn(Foo, :listen, [])
#PID<0.117.0>
iex> send(pid, "hello")
received hello
But if you send message to the process again, nothing happens, the process is dead.
iex> Process.alive?(pid)
false
To fix this, we need to call listen recursively:
defmodule Foo do
def listen do
receive do
msg -> IO.puts("received #{msg}")
end
listen()
end
end
Linked Process
If you need to make sure the process is spawned succssfully. Use
spawn_link instead of spawn will link the newly created process to
the current one. Two linked processes will receive exit signals from
one anther.
defmodule Foo do
def boom do
exit(:boom)
end
end
pid = spawn_link(Foo, :boom , [])
** (EXIT from #PID<0.104.0>) shell process exited with reason: :boom
By default the exit signal will crash the process.
Trap the exit signal
Using Process.flag(:trap_exit, true) to trap exit notifications.
defmodule Foo do
def boom do
exit(:boom)
end
def run do
Process.flag(:trap_exit, true)
spawn_link(Foo, :boom, [])
receive do
{:EXIT, _pid, reason} -> IO.puts("Exit reason: #{reason}")
end
end
end
iex> Foo.run
Exit reason: boom
Monitoring
Another way is to use spawn_monitor to receive process down signal:
defmodule Foo do
def boom do
exit(:boom)
end
def run do
spawn_monitor(Foo, :boom , [])
receive do
{:DOWN, _ref, :process, _from_pid, reason} -> IO.puts("Exit reason: #{reason}")
end
end
end
Foo.run