Timeouts in Erlang
Timeouts are important for programs that connect to external resources or that otherwise need to bound execution time. Implementing timeouts in Erlang is straightforward using the timer
module and message passing.
-module(timeouts).
-export([main/0]).
main() ->
% For our example, suppose we're executing an external
% call that returns its result after 2s. We'll use
% a separate process to simulate this delay.
Pid1 = spawn(fun() ->
timer:sleep(2000),
self() ! {result, "result 1"}
end),
% Here we implement a timeout using the receive..after construct.
% We'll wait for a message from Pid1 for 1 second.
Result1 = receive
{result, Res1} ->
io:format("~s~n", [Res1])
after 1000 ->
io:format("timeout 1~n")
end,
% If we allow a longer timeout of 3s, then the receive
% from Pid2 will succeed and we'll print the result.
Pid2 = spawn(fun() ->
timer:sleep(2000),
self() ! {result, "result 2"}
end),
Result2 = receive
{result, Res2} ->
io:format("~s~n", [Res2])
after 3000 ->
io:format("timeout 2~n")
end.
Running this program shows the first operation timing out and the second succeeding.
$ erl -noshell -s timeouts main -s init stop
timeout 1
result 2
In this Erlang version:
We use separate processes (created with
spawn
) to simulate the delayed operations instead of goroutines.Instead of channels, we use Erlang’s built-in message passing mechanism.
The
select
statement with timeout is replaced by Erlang’sreceive..after
construct, which allows us to specify a timeout directly.We use
timer:sleep/1
to introduce delays, similar totime.Sleep
in the original example.The
io:format/2
function is used for output, replacingfmt.Println
.
This example demonstrates how to implement timeouts in Erlang, which is a crucial feature for programs that need to bound execution time or interact with external resources.