+(in-package :locked-queue)
+
+(declaim (optimize (space 0) (speed 0) (safety 3) (debug 3)))
+
+(defclass locked-queue ()
+ ((queue :initform nil)
+ (mutex :initform (sb-thread:make-mutex :name "queue lock"))
+ (waitq :initform (make-waitqueue))))
+
+(defun create ()
+ (make-instance 'locked-queue))
+
+(defmethod dequeue ((q locked-queue))
+ (with-slots (queue mutex waitq) q
+ (with-mutex (mutex)
+ (if (or (null queue)
+ (null (first queue)))
+ (condition-wait waitq mutex))
+ (prog1 (first (car queue))
+ (setf (car queue)
+ (rest (car queue)))))))
+
+(defmethod enqueue ((q locked-queue) value)
+ (with-slots (queue mutex waitq) q
+ (with-mutex (mutex)
+ (let ((last (list value)))
+ (if (null (first queue))
+ (progn
+ (setf queue (cons last last))
+ (condition-notify waitq))
+ (progn
+ (setf (rest (cdr queue))
+ last
+ (cdr queue) last)
+ (cons (car queue) last)))))))