Closing Channels in OCaml

In this example, we’ll demonstrate how to close channels in OCaml using the Event module from the Lwt library. Closing a channel indicates that no more values will be sent on it. This can be useful to communicate completion to the channel’s receivers.

open Lwt
open Lwt_channel

let main () =
  let jobs = Lwt_channel.create_bounded 5 in
  let done_signal = Lwt_mvar.create_empty () in

  let worker () =
    let rec loop () =
      Lwt_channel.recv jobs >>= function
      | Some j ->
          Lwt_io.printf "received job %d\n" j >>= loop
      | None ->
          Lwt_io.printl "received all jobs" >>= fun () ->
          Lwt_mvar.put done_signal true
    in
    loop ()
  in

  let _ = worker () in

  let send_jobs () =
    let rec send_job j =
      if j <= 3 then
        Lwt_channel.send jobs j >>= fun () ->
        Lwt_io.printf "sent job %d\n" j >>= fun () ->
        send_job (j + 1)
      else
        Lwt.return_unit
    in
    send_job 1 >>= fun () ->
    Lwt_channel.close jobs >>= fun () ->
    Lwt_io.printl "sent all jobs"
  in

  send_jobs () >>= fun () ->
  Lwt_mvar.take done_signal >>= fun _ ->

  Lwt_channel.recv jobs >>= function
  | Some _ -> Lwt_io.printl "received more jobs: true"
  | None -> Lwt_io.printl "received more jobs: false"

let () = Lwt_main.run (main ())

In this OCaml version, we use Lwt_channel to create a bounded channel for jobs and Lwt_mvar for synchronization. The worker function repeatedly receives from the jobs channel until it’s closed, then signals completion through the done_signal mvar.

We send 3 jobs to the worker over the jobs channel, then close it. We await the worker using the synchronization approach with Lwt_mvar.

Finally, we attempt to receive from the closed channel to demonstrate that it returns None when closed.

To run this program, you would save it as closing_channels.ml and compile it with the Lwt library:

$ ocamlfind ocamlc -package lwt,lwt.unix -linkpkg -o closing_channels closing_channels.ml
$ ./closing_channels
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs
received more jobs: false

This example demonstrates how to use channels and synchronization primitives in OCaml with the Lwt library, which provides a concurrent programming model similar to goroutines in Go.