Title here
Summary here
Timeouts are important for programs that connect to external resources or that otherwise need to bound execution time. Implementing timeouts in OCaml can be done using the Unix
module and the select
function.
open Unix
let () =
(* For our example, suppose we're executing an external
call that returns its result after 2 seconds. We'll
use a pipe to simulate this behavior. *)
let (read_fd, write_fd) = pipe () in
let _ = Thread.create (fun () ->
Thread.delay 2.0;
let _ = write write_fd "result 1" 0 8 in
close write_fd
) () in
(* Here's the select implementing a timeout.
We'll wait for either data to be available on the pipe
or for the timeout to occur. *)
match select [read_fd] [] [] 1.0 with
| [], _, _ ->
print_endline "timeout 1"
| [ready_fd], _, _ ->
let buffer = Bytes.create 8 in
let _ = read ready_fd buffer 0 8 in
print_endline (Bytes.to_string buffer)
| _ -> failwith "Unexpected select result";
close read_fd;
(* If we allow a longer timeout of 3s, then the read
from the pipe will succeed and we'll print the result. *)
let (read_fd, write_fd) = pipe () in
let _ = Thread.create (fun () ->
Thread.delay 2.0;
let _ = write write_fd "result 2" 0 8 in
close write_fd
) () in
match select [read_fd] [] [] 3.0 with
| [], _, _ ->
print_endline "timeout 2"
| [ready_fd], _, _ ->
let buffer = Bytes.create 8 in
let _ = read ready_fd buffer 0 8 in
print_endline (Bytes.to_string buffer)
| _ -> failwith "Unexpected select result";
close read_fd
Running this program shows the first operation timing out and the second succeeding.
$ ocamlc unix.cma threads.cma timeouts.ml -o timeouts
$ ./timeouts
timeout 1
result 2
In this OCaml version:
Unix.pipe
function to create a pipe, which simulates an external call.Thread.create
to start a new thread that writes to the pipe after a delay.Unix.select
function is used to implement the timeout. It waits for either data to be available on the pipe or for the timeout to occur.select
.Thread.delay
function is used to simulate the delay in the “external call”.Note that OCaml’s standard library doesn’t have a direct equivalent to Go’s channels, so we use pipes and threads to achieve similar functionality. The select
function in OCaml works with file descriptors rather than channels.