Are messages sent to self immediately delivered?

Basically, with this elixir function:

  fn ->
    send(self(), :hello)

    receive do
      msg -> {:received, msg}
    after
      0 -> :not_received
    end
  end

Will it always return {:received, msg}?

Thank you.

Edit: I believe so because I suppose that the send(…) function returns after the message has been written on the mailbox at the VM level ; but I don’t know how to verify it.

1 Like

What do you mean by that?

defmodule Message do
  def test() do
    send(self(), :hello)

    receive do
      msg -> {:received, msg}
    after
      0 -> :not_received
    end
  end
end

Then in iex:

iex(1)> Message.test()
{:received, :hello}

It will receive it, but not necessarily immediately. It’s perfectly possible for a send from another process to put something in the mailbox before the send in this code.

5 Likes

And largely because of this :handle_continue was added to OTP.

4 Likes

It will always return {:received, msg}, but msg is not necessarily what you have send before.

send is a synchronous operation, so it will not return before the message has been copied to the recipients mailbox, this means, that there will always something to receive. At the same time though, there might already be something in the mailbox when you did the send, then this will be received first as you receive unselectively.

6 Likes

Hi,

Yes I forgot to mention that, I know the mailbox can contain previous messages and my interrogation was more about a race condition between sending and receiving.

Thank you for confirming that send() is synchronous.

And thank you all for your answers.

2 Likes

Sending to yourself is exactly the same as sending to another process. The message will be copied to the heap of the receiving process and then added to the END of the message queue. So if you send to yourself there will be no need to the copy but the message ends up at the end of the message queue. So when you do a receive it will start scanning from the front of the message queue.

The whole process is extreme;ly consistent.

6 Likes

Oh that also explains why several messages sent from the same process to another process are also guaranteed to be delivered in order.

Then I guess that if I (me, a process :slight_smile: ) am monitoring a process, and that process sends me a message, and then exits, I will always receive the message before the 'DOWN' message.

2 Likes

Yes, the BEAM guarantees that all signals [*] sent from one process to another will arrive in the same order in which they were sent.

[*] Signals here is all the communication between processes which includes messages and other information as well. Lukas Larsson gave a very good talk about it here Process Signals in OTP-21

9 Likes