Untitled notebook
Mix.install([
{:kino, "~> 0.9.2"}
])
PIDs
self()
Spawning
To create a new process, we can use spawn/1:
spawn(fn ->
Process.sleep(1000)
IO.puts("PID #{inspect(self())} is done")
end)
IO.puts("Spawned a process from #{inspect(self())}")
Sending and Receiving Messages
- Processes communicate via messages
- A process can send or receive messages
- Similar guarantees to TCP
- Messages are delivered in the same order they are sent
- All messages are eventually delivered if the destination process stays alive
- No guarantee about what the destination process does with the message
send(self(), :hello)
receive do
message -> message
end
receive do
message -> message
after
1000 -> :timeout
end
send(self(), 102)
# Complete: with timeout and different clauses
receive do
%{} -> :map
number when is_number(number) -> :number
_other -> :other
after
1000 -> :timeout
end
Kino.Process.render_seq_trace(fn ->
pid =
spawn(fn ->
type =
receive do
%{} -> :map
number when is_number(number) -> :number
_other -> :other
after
1000 -> :timeout
end
IO.puts("Type is #{inspect(type)}")
end)
send(pid, 123)
end)
Parallel Map
defmodule ParallelEnum do
def map(enum, fun) when is_function(fun, 1) do
raise "not implemented yet"
end
end
ExUnit.start()
defmodule ParallelEnumTests do
use ExUnit.Case
test "works like Enum.map/1" do
assert ParallelEnum.map(1..4, &Integer.to_string/1) == ["1", "2", "3", "4"]
end
test "work in parallel " do
{elapsed, _result} =
:timer.tc(fn ->
ParallelEnum.map(1..4, fn _ -> Process.sleep(500) end)
end)
assert elapsed < 600
end
end
ExUnit.run()
Kino.Process.render_seq_trace(fn ->
1..3
|> Task.async_stream(fn _ ->
Process.sleep(Enum.random(50..200))
end)
|> Stream.run()
end)
Links and Monitors
Kino.Process.render_seq_trace(fn ->
crasher_pid =
spawn(fn ->
Process.sleep(1000)
raise "I crash 👹"
end)
linked_pid =
spawn(fn ->
Process.link(crasher_pid)
Process.sleep(:infinity)
end)
Process.sleep(1100)
Process.alive?(linked_pid)
end)
pid =
spawn(fn ->
Process.sleep(500)
:i_finished_just_fine
end)
ref = Process.monitor(pid)
receive do
{:DOWN, ^ref, _type, _pid, _reason} = down_message ->
down_message
end