Closing Channels in Clojure
In Clojure, we can demonstrate the concept of closing channels using core.async, which provides CSP-style concurrency. Here’s an example that shows how to close channels and handle the completion of work:
(ns closing-channels-example
(:require [clojure.core.async :as async :refer [>! <! >!! <!! go chan close! buffer]]))
(defn main []
(let [jobs (chan 5)
done (chan)]
; Worker process
(go
(loop []
(if-let [j (<! jobs)]
(do
(println "received job" j)
(recur))
(do
(println "received all jobs")
(>! done true)))))
; Send jobs
(doseq [j (range 1 4)]
(>!! jobs j)
(println "sent job" j))
(close! jobs)
(println "sent all jobs")
; Wait for worker to finish
(<!! done)
; Check if channel is closed
(if-let [_ (<!! jobs)]
(println "received more jobs: true")
(println "received more jobs: false"))))
(main)
In this example, we use core.async
to create channels and demonstrate the concept of closing them. Here’s a breakdown of what’s happening:
We create two channels:
jobs
(with a buffer of 5) anddone
.We start a worker process using
go
, which repeatedly receives fromjobs
. If a job is received, it’s processed. If the channel is closed and empty, the worker completes its work and signals on thedone
channel.In the main thread, we send three jobs to the worker over the
jobs
channel, then close it.We wait for the worker to finish by taking from the
done
channel.Finally, we attempt to receive from the closed
jobs
channel to demonstrate that it returnsnil
when closed and empty.
To run this program, you would typically save it in a file (e.g., closing_channels.clj
) and run it using a Clojure environment. The output would look something like this:
sent job 1
sent job 2
sent job 3
sent all jobs
received job 1
received job 2
received job 3
received all jobs
received more jobs: false
This example demonstrates how closing a channel can be used to signal the completion of work to a receiver, a common pattern in concurrent programming.