
def loop(some_int) do
receive do
{:add, value} ->
loop(some_int + value)
end
endStack serverdefmodule StackServer do
def loop(state) do
receive do
{:push, value} ->
new_state = [value | state]
loop(new_state)
{:pop, sender} ->
[value | new_state] = state
send(sender, value)
loop(new_state)
end
end
end
push functiondefmodule StackServer do
def push(pid, value) do
send(pid, {:push, value})
end
end
pop synchronousdefmodule StackServer do
def pop(pid) do
ref = make_ref()
send(pid, {:pop, self(), ref})
receive do
{^ref, value} -> value
end
end
def loop(state) do
receive do
{:pop, sender, ref} ->
[value | new_state] = state
send(sender, {ref, value})
loop(new_state)
end
end
end
Two main primitives
link: non-stackable bidirectional linkif linked process dies, I must do something
monitor: stackable unidirectional linkif monitored process dies, it's not really my problem
Default behavior: if you die, I die
iex(1)> spawn_link(fn -> raise "die!" end)
** (EXIT from #PID<0.98.0>) an exception was raised:
** (RuntimeError) die!
(stdlib) erl_eval.erl:668: :erl_eval.do_apply/6
Interactive Elixir (1.4.2) - press Ctrl+C to exit (type h() ENTER for help)
22:27:50.586 [error] Process #PID<0.100.0> raised an exception
** (RuntimeError) die!
(stdlib) erl_eval.erl:668: :erl_eval.do_apply/6New link behavior: if you die, I get a message
iex(1)> Process.flag(:trap_exit, true)
false
iex(2)> spawn_link(fn -> raise "die!" end)
#PID<0.101.0>
iex(3)>
22:30:04.530 [error] Process #PID<0.101.0> raised an exception
** (RuntimeError) die!
(stdlib) erl_eval.erl:668: :erl_eval.do_apply/6
flush()
{:EXIT, #PID<0.101.0>,
{%RuntimeError{message: "die!"},
[{:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 668]}]}}Processes are usually divided in two types
Supervisor are responsible for restarting workers
4 main strategies
Given processes A,B,C, if B dies
BA,B,CB,CBProcesses in simple one for one must have the same type (i.e. call the same function) and are usually spawned dynamically
Application is usually composed of many supervisors and workers
