Next: , Previous: Semaphores, Up: Threading


12.5 Waitqueue/condition variables

These are based on the POSIX condition variable design, hence the annoyingly CL-conflicting name. For use when you want to check a condition and sleep until it's true. For example: you have a shared queue, a writer process checking “queue is empty” and one or more readers that need to know when “queue is not empty”. It sounds simple, but is astonishingly easy to deadlock if another process runs when you weren't expecting it to.

There are three components:

Important stuff to be aware of:

     (defvar *buffer-queue* (make-waitqueue))
     (defvar *buffer-lock* (make-mutex :name "buffer lock"))
     
     (defvar *buffer* (list nil))
     
     (defun reader ()
       (with-mutex (*buffer-lock*)
         (loop
          (condition-wait *buffer-queue* *buffer-lock*)
          (loop
           (unless *buffer* (return))
           (let ((head (car *buffer*)))
             (setf *buffer* (cdr *buffer*))
             (format t "reader ~A woke, read ~A~%"
                     *current-thread* head))))))
     
     (defun writer ()
       (loop
        (sleep (random 5))
        (with-mutex (*buffer-lock*)
          (let ((el (intern
                     (string (code-char
                              (+ (char-code #\A) (random 26)))))))
            (setf *buffer* (cons el *buffer*)))
          (condition-notify *buffer-queue*))))
     
     (make-thread #'writer)
     (make-thread #'reader)
     (make-thread #'reader)

— Structure: sb-thread:waitqueue

Class precedence list: waitqueue, structure-object, t

Waitqueue type.

— Function: sb-thread:make-waitqueue &key name

Create a waitqueue.

— Function: sb-thread:waitqueue-name instance

Name of a queue. Can be assingned to using setf. Queue names can be arbitrary printable objects, and need not be unique.

— Function: sb-thread:condition-wait queue mutex

Atomically release mutex and enqueue ourselves on queue. Another thread may subsequently notify us using condition-notify, at which time we reacquire mutex and return to the caller.

— Function: sb-thread:condition-notify queue &optional n

Notify n threads waiting on queue. The same mutex that is used in the corresponding condition-wait must be held by this thread during this call.

— Function: sb-thread:condition-broadcast queue

Notify all threads waiting on queue.