Hi Experts,
I am trying to understand the Process Flow when spawning new Processes, for this I wrote a simple program to spawn a process and wait
defmodule Link do
import :timer, only: [ sleep: 1 ]
def sad_function do
IO.puts "I am another process..Now I sleep zzzzz..."
sleep 1000
exit(:boom)
end
def run do
Process.flag(:trap_exit, true)
# Doesnt know whats heppening with the other process
# spawn(Link, :sad_function, [])
#The Below knows when the lined process Exists
spawn_link(Link, :sad_function, [])
IO.puts "I have spawned and I wait.."
receive do
msg ->
IO.inspect "Wait over..Message received"
IO.inspect msg
IO.puts "Is Tuple? #{inspect is_tuple(msg)}"
after 2000 ->
IO.puts "Nothing is happening! Are we dead?"
end
IO.puts "After Receive Block!"
end
end
Link.run
The Output is as follows:
λ elixir -r link.exs
I have spawned and I wait..
I am another process..Now I sleep zzzzz...
"Wait over..Message received"
{:EXIT, #PID<0.77.0>, :boom}
Is Tuple? true
After Receive Block!
Question: Why is the After Receive Block logged after the receive Block has been processes, my idea was that the receive block in the run() definition is kind of a callback and the rest of the code will get processed sequentially and the receive block whenever a message is received from the sad_function?
receive do blocks the calling process. Each process is isolated, so this doesn’t block any other process, but it is blocking for the process that calls receive. This makes it very easy to receive a message and then use it in normal code:
# receives the first 10 messages
messages = for _ <- 1..10 do
receive do
msg -> msg
end
end
messages |> IO.inspect
Yeah okay that’s a little bit different than how i was expecting . but thanks for the explanation.
I have a bit of node background so I was thinking more callback style . Good I will have to think a little bit differently then I am used to.
Interesting here is that the more high-level abstraction called GenServer that is commonly (almost always) used for processes over plain sends and receives, also adheres to a callback-style API, because the receive loop is one of the things that it has abstracted away from you
Very nice observation. Maybe a GenServer can be a little bit more easier to understand for node people. But anyways, don’t know if you are used to it, but in ES2016 there is the await function, that actually does pretty something similar to what receive do.