Select in Erlang

Our example demonstrates how to use Erlang’s receive statement to wait on multiple message operations. Combining processes and message passing with receive is a powerful feature of Erlang.

-module(select).
-export([main/0]).

main() ->
    % For our example we'll receive from two processes.
    Pid1 = spawn(fun() -> 
        timer:sleep(1000),
        self() ! {c1, "one"}
    end),
    Pid2 = spawn(fun() -> 
        timer:sleep(2000),
        self() ! {c2, "two"}
    end),

    % Each process will send a message after some amount
    % of time, to simulate e.g. blocking RPC operations
    % executing in concurrent processes.

    % We'll use receive to await both of these values
    % simultaneously, printing each one as it arrives.
    receive_messages(2).

receive_messages(0) ->
    ok;
receive_messages(N) ->
    receive
        {c1, Msg1} ->
            io:format("received ~p~n", [Msg1]);
        {c2, Msg2} ->
            io:format("received ~p~n", [Msg2])
    end,
    receive_messages(N-1).

To run the program:

$ erlc select.erl
$ erl -noshell -s select main -s init stop
received "one"
received "two"

We receive the values "one" and then "two" as expected.

Note that the total execution time is only ~2 seconds since both the 1 and 2 second timer:sleep() calls execute concurrently in separate processes.

In Erlang, we use processes and message passing instead of goroutines and channels. The receive statement in Erlang is similar to the select statement in other languages, allowing us to wait for messages from multiple sources.