The communication model (among processes) in Erlang is message passing. Erlang processes share no memory. The way that processes communicate is via (asynchronous) message passing. Every process (even the shell) holds a mailbox queue where incoming messages are placed until received by the process. Message passing is asynchronous because the sending process does not block on send. On the other hand, receiving a message in Erlang is a blocking operation.
Characteristics
In this subsection I will describe some of the characteristics of message passing in Erlang.
Asynchronous
Message passing in Erlang is a non-blocking operation.
Data Copy
The message’s data are copied from the sending process to the receiver’s message queue, so the receiver gets a fresh copy of the data.
Ordering
Erlang runtime guarantees that if two messages are sent from node A to node B and both are delivered, then the ordering of these messages is kept (because ordering).
Successful Send
The send operation always succeeds (even if the target is a non-existing process) and evaluates to the data sent. An exception is when trying to send data to a non-existing registered process.
Sending Messages
Erlang uses the exclamation mark (!) as the operator for sending a message.
Syntax:
1 2 |
|
Send multiple messages “at once”:
1 2 3 |
|
Example:
As I have mentioned before, the shell is nothing more than a process. As a process, it has a message queue. In order to print and empty the shell’s message queue we can use the flush/0 BIFs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
Receiving Messages
Erlang uses pattern matching for receiving messages (same as in function clause selection and the case statement). The receive statement is used to deliver messages from the message queue.
Syntax:
1 2 3 4 5 6 7 8 |
|
Receiving Order
The message processing is done in a FIFS (First In – First Served) order. Every incoming message is placed in the tail of the process’ message queue. When a receive statement is meet the following processing happens:
1. The first message (head of the message queue) is pattern matched against the first receive clause. If match, execute the clause’s body, else go to the next step.
2. The same message is pattern matched against the second (if any) receive clause. If match, execute the clause’s body, else go to the next step.
3. …
4. The same message is pattern matched against the last clause. If match, execute the clause’s body, else go to the next step.
5. The same iterative process starts again from step 1, but now with the next message from the message queue.
The message (if any) that is delivered through receive is removed from the message queue.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Example running:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Timeout
Receive is a blocking statement; it blocks until a message that matches one of the clauses is placed in the incoming message queue. Erlang allows the programmer to explicitly unblock the receive statement using a timeout (if a matching message is not delivered until the timeout expires). The complete format of receive statement, including the after construct.
Syntax:
1 2 3 4 5 6 7 8 9 10 |
|
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Example running:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|