Search code examples
asynchronousconcurrencyerlangmessage-queue

In Erlang, is sending to self atomic?


As far as I know Erlang, processes always receive the first message [to arrive] in their mailbox, out of those matching a pattern. I am curious if that can be used to gain the following assumption:

If a process a does

self() ! its_me,
b ! go,
receive
   X -> X
end.

And b does

receive
  _ -> a ! its_not_me
end

then do I have a guarantee that a will receive the message from itself first (X = its_me)?


Some of my reasoning

The question relates to how send-to-self or send-within-node is implemented; whether it puts the message in the queue right away, or if there is some moment when the message is "on its way" and can be overtaken by other messages.

If both a and b would send their messages to some other c, then it is clearly non-deterministic whether c would receive its_me or its_not_me. Here however, I have more premises:

  • a sends to a before a sends to b
  • b's mbox receives from a before b receives from a
  • b receives from a before b sends to a
  • (Conclusion) a completes the send to itself necessarily before its message box receives the message from b

What I want to know is whether the conclusion implies that a's mbox receives the message from a before it receives it from b


Solution

  • As far as I can tell, the theoretical answer is no. From the Delivery of Signals manual section:

    The only signal ordering guarantee given is the following: if an entity sends multiple signals to the same destination entity, the order is preserved; that is, if A sends a signal S1 to B, and later sends signal S2 to B, S1 is guaranteed not to arrive after S2. Note that S1 may, or may not have been lost.

    That is not the case here: neither a nor b sends multiple signals to the same destination entity.

    This answer is theoretical in the sense that an Erlang implementation that delivered the message its_not_me first would not be considered incorrect. In practice I would consider it very unlikely that an Erlang implementation would actually do this, for the reason you pointed out in your question.