Processes
BEAM processes are lightweight (≈2–3 KB initial memory), isolated (no shared memory), preemptively scheduled, and communicate only by message passing.
BEAM processes are lightweight (≈2–3 KB initial memory), isolated (no shared memory), preemptively scheduled, and communicate only by message passing. A single node can run millions of them.
29.1 spawn, send, receive
send/2 is asynchronous and never fails (even if the process is dead).
Each process has a mailbox; receive scans for the first message matching any pattern (selective receive). Non-matching messages stay in the mailbox.
flush() in IEx prints and empties the mailbox.
pid = spawn(fn -> IO.puts("Hello from #{inspect(self())}") end)
Process.alive?(pid)
parent = self()
spawn(fn -> send(parent, {:result, 42}) end)
receive do
{:result, value} -> IO.puts("Got #{value}")
after
1_000 -> IO.puts("Timeout")
end29.2 Stateful processes via recursion
This is the essence of what GenServer abstracts.
defmodule Counter do
def start(initial \\ 0), do: spawn(fn -> loop(initial) end)
defp loop(count) do
receive do
{:increment, by} ->
loop(count + by)
{:get, caller} ->
send(caller, {:count, count})
loop(count)
:stop ->
:ok
end
end
end
pid = Counter.start()
send(pid, {:increment, 5})
send(pid, {:get, self()})
receive do {:count, c} -> c end # 529.3 Process registration
Process.register(pid, :counter)
send(:counter, {:increment, 1})
Process.whereis(:counter)
Process.registered()29.4 Process utilities
self()
Process.info(pid) # memory, message_queue_len, ...
Process.info(pid, :message_queue_len)
Process.sleep(100)
Process.send_after(self(), :tick, 1_000) # timers
ref = Process.send_after(self(), :x, 5000); Process.cancel_timer(ref)
Process.exit(pid, :kill)
Process.flag(:trap_exit, true)
Process.put(:key, :value) # process dictionary (use rarely)
Process.get(:key)
Process.list() |> length()29.5 References & request/response
ref = make_ref()
send(server, {:request, self(), ref, :data})
receive do
{^ref, reply} -> reply # pin the ref to match only our reply
after 5000 -> {:error, :timeout}
end