Waitgroups in Lisp
Our example demonstrates how to wait for multiple threads to finish using a semaphore. In Lisp, we’ll use the bordeaux-threads
library for threading capabilities.
First, let’s define our worker function:
(defun worker (id)
(format t "Worker ~D starting~%" id)
;; Sleep to simulate an expensive task
(sleep 1)
(format t "Worker ~D done~%" id))
This function simulates a task by printing a start message, sleeping for a second, and then printing a completion message.
Now, let’s set up our main function:
(defun main ()
(let ((semaphore (bt:make-semaphore :count 0)))
;; Launch several threads and increment the semaphore counter for each
(dotimes (i 5)
(bt:make-thread
(lambda ()
(unwind-protect
(worker (1+ i))
(bt:signal-semaphore semaphore)))
:name (format nil "Worker-~D" (1+ i))))
;; Wait for all threads to finish
(dotimes (i 5)
(bt:wait-on-semaphore semaphore))))
Here’s what’s happening in the main
function:
- We create a semaphore with an initial count of 0.
- We launch 5 threads, each running our
worker
function. - Each thread is wrapped in an
unwind-protect
form, which ensures that the semaphore is signaled even if an error occurs. - After launching all threads, we wait on the semaphore 5 times, effectively waiting for all threads to complete.
To run this program:
$ sbcl --load waitgroups.lisp
* (main)
Worker 1 starting
Worker 2 starting
Worker 3 starting
Worker 4 starting
Worker 5 starting
Worker 1 done
Worker 2 done
Worker 3 done
Worker 4 done
Worker 5 done
NIL
*
The order of workers starting up and finishing is likely to be different for each invocation.
Note that this approach doesn’t provide a straightforward way to propagate errors from workers. For more advanced use cases, you might need to implement additional error handling mechanisms.
Also, remember that you’ll need to have the bordeaux-threads
library installed and loaded to run this code. You can install it using Quicklisp:
(ql:quickload :bordeaux-threads)
This example demonstrates how to use threads and semaphores in Lisp to achieve similar functionality to WaitGroups in other languages.