Channel Buffering in Erlang

Our example demonstrates channel buffering in Erlang. Here’s the full source code:

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

main() ->
    % Here we create a process with a message queue that can buffer up to 2 messages
    Pid = spawn(fun() -> receive_loop(2) end),

    % Because this process's message queue is buffered, we can send these
    % values without a corresponding concurrent receive
    Pid ! {self(), "buffered"},
    Pid ! {self(), "channel"},

    % Later we can receive these two values as usual
    receive
        {Pid, Message1} -> io:format("~s~n", [Message1])
    end,
    receive
        {Pid, Message2} -> io:format("~s~n", [Message2])
    end.

receive_loop(0) ->
    ok;
receive_loop(N) ->
    receive
        {From, Message} ->
            From ! {self(), Message},
            receive_loop(N - 1)
    end.

In Erlang, we don’t have built-in buffered channels like in some other languages. However, we can achieve similar functionality using processes and their message queues.

We create a process that acts as our “buffered channel”. This process has a message queue that can hold messages, effectively acting as a buffer.

We then send two messages to this process without immediately receiving them. This is analogous to sending values to a buffered channel.

Finally, we receive these two messages, printing them out. This is similar to receiving from a buffered channel.

The receive_loop/1 function implements the buffering behavior. It receives up to N messages before stopping, effectively limiting the buffer size.

To run the program, save it as channel_buffering.erl and use the Erlang shell:

$ erl
1> c(channel_buffering).
{ok,channel_buffering}
2> channel_buffering:main().
buffered
channel
ok

This example demonstrates how to implement a concept similar to buffered channels in Erlang using processes and message passing.