Closing Channels in Racket
#lang racket
(require racket/channel)
; In this example we'll use a `jobs` channel to communicate work to be done
; from the main thread to a worker thread. When we have no more jobs for
; the worker we'll close the `jobs` channel.
(define (main)
(define jobs (make-channel 5))
(define done (make-channel))
; Here's the worker thread. It repeatedly receives from `jobs` with
; `(channel-try-get jobs)`. This function returns two values: the received
; value and a boolean indicating whether the receive was successful.
; We use this to notify on `done` when we've worked all our jobs.
(thread
(lambda ()
(let loop ()
(define-values (job more) (channel-try-get jobs))
(cond
[more
(printf "received job ~a\n" job)
(loop)]
[else
(printf "received all jobs\n")
(channel-put done #t)]))))
; This sends 3 jobs to the worker over the `jobs` channel, then closes it.
(for ([j (in-range 1 4)])
(channel-put jobs j)
(printf "sent job ~a\n" j))
(channel-close jobs)
(printf "sent all jobs\n")
; We await the worker using the synchronization approach we saw earlier.
(channel-get done)
; Reading from a closed channel succeeds immediately, returning #f.
; The optional second return value is #t if the value received was
; delivered by a successful send operation to the channel, or #f if
; the channel is closed and empty.
(define-values (_ ok) (channel-try-get jobs))
(printf "received more jobs: ~a\n" ok))
(main)
To run this program, save it as closing-channels.rkt
and execute it using Racket:
$ racket closing-channels.rkt
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: #f
In this Racket version, we use the racket/channel
module to work with channels, which are similar to Go’s channels. The make-channel
function creates a new channel, and channel-put
and channel-get
are used to send and receive values respectively.
Instead of goroutines, Racket uses threads. The thread
function starts a new thread with the given function.
The channel-try-get
function is used to receive from a channel, returning two values: the received value and a boolean indicating whether the receive was successful. This is similar to the two-value form of channel receive in Go.
Closing a channel in Racket is done with channel-close
. After a channel is closed, channel-try-get
will return #f for both values.
The concept of closing channels in Racket is similar to Go, allowing us to signal that no more values will be sent on the channel.