(require :sb-queue) (defpackage :sb-queue-test (:use :cl :sb-thread :sb-queue) (:export)) (in-package :sb-queue-test) (let ((q (make-queue :name 'test-q :initial-contents '(1 2 3)))) (enqueue 4 q) (assert (eq 'test-q (queue-name q))) (multiple-value-bind (v ok) (dequeue q) (assert (eql 1 v)) (assert (eq t ok))) (assert (equal (list-queue-contents q) (list 2 3 4)))) (assert (equal (list nil nil) (multiple-value-list (dequeue (make-queue))))) (assert (equal (list nil t) (multiple-value-list (dequeue (make-queue :initial-contents '(nil)))))) (let ((x (make-instance 'structure-object)) (y (make-queue))) (assert (not (typep x 'queue))) (assert (not (queuep x))) (assert (typep y 'queue)) (assert (queuep y))) (let ((q (make-queue :initial-contents (vector 1 2 3 4 5)))) (assert (= 5 (queue-count q))) (enqueue 'foo q) (assert (= 6 (queue-count q))) (dequeue q) (assert (= 5 (queue-count q))) (dequeue q) (assert (= 4 (queue-count q))) (dequeue q) (assert (= 3 (queue-count q))) (dequeue q) (assert (= 2 (queue-count q))) (dequeue q) (assert (= 1 (queue-count q))) (assert (not (queue-empty-p q))) (dequeue q) (assert (= 0 (queue-count q))) (assert (queue-empty-p q)) (dequeue q) (assert (= 0 (queue-count q))) (assert (queue-empty-p q))) #+sb-thread (let* ((q (make-queue)) (w (make-semaphore)) (r (make-semaphore)) (n 100000) (schedulers (list (make-thread (lambda () (signal-semaphore r) (wait-on-semaphore w) (dotimes (i n) (enqueue (cons :a i) q)))) (make-thread (lambda () (signal-semaphore r) (wait-on-semaphore w) (dotimes (i n) (enqueue (cons :b i) q)))) (make-thread (lambda () (signal-semaphore r) (wait-on-semaphore w) (dotimes (i n) (enqueue (cons :c i) q)))) (make-thread (lambda () (signal-semaphore r) (wait-on-semaphore w) (dotimes (i n) (enqueue (cons :d i) q))))))) (loop repeat 4 do (wait-on-semaphore r)) (signal-semaphore w 4) (mapc #'join-thread schedulers) (let (a b c d) (loop (multiple-value-bind (item ok) (dequeue q) (cond (item (assert ok) (case (car item) (:a (push (cdr item) a)) (:b (push (cdr item) b)) (:c (push (cdr item) c)) (:d (push (cdr item) d)))) (t (assert (not ok)) (return))))) (labels ((check-list (list) (when list (if (cdr list) (when (= (first list) (1- (second list))) (check-list (cdr list))) (= (first list) (1- n)))))) (assert (eq t (check-list (nreverse a)))) (assert (eq t (check-list (nreverse b)))) (assert (eq t (check-list (nreverse c)))) (assert (eq t (check-list (nreverse d))))))) #+sb-thread (let ((q (make-queue)) (w (make-semaphore)) (r (make-semaphore))) (dotimes (i 1000000) (enqueue i q)) (flet ((dq () (signal-semaphore r) (wait-on-semaphore w) (let ((last -1)) (loop (multiple-value-bind (x ok) (dequeue q) (cond (x (if (and (> x last) ok) (setf last x) (return (list last x ok)))) (t (if (not ok) (return t) (return (list last x ok)))))))))) (let ((deschedulers (list (make-thread #'dq) (make-thread #'dq) (make-thread #'dq) (make-thread #'dq)))) (loop repeat 4 do (wait-on-semaphore r)) (signal-semaphore w 4) (mapcar (lambda (th) (assert (eq t (join-thread th)))) deschedulers)))) #+sb-thread (let* ((q (make-queue)) (w (make-semaphore)) (r (make-semaphore)) (n 100000) (schedulers (list (make-thread (lambda () (signal-semaphore r) (wait-on-semaphore w) (dotimes (i n) (enqueue (cons :a i) q)))) (make-thread (lambda () (signal-semaphore r) (wait-on-semaphore w) (dotimes (i n) (enqueue (cons :b i) q)))) (make-thread (lambda () (signal-semaphore r) (wait-on-semaphore w) (dotimes (i n) (enqueue (cons :c i) q)))) (make-thread (lambda () (signal-semaphore r) (wait-on-semaphore w) (dotimes (i n) (enqueue (cons :d i) q))))))) (flet ((dq () (let ((a -1) (ac 0) (b -1) (bc 0) (c -1) (cc 0) (d -1) (dc 0)) (signal-semaphore r) (wait-on-semaphore w) (loop (multiple-value-bind (item ok) (dequeue q) (cond (item (let ((n (cdr item))) (macrolet ((test (name c) `(if (< ,name n) (progn (setf ,name n) (incf ,c)) (return nil)))) (ecase (car item) (:a (test a ac)) (:b (test b bc)) (:c (test c cc)) (:d (test d dc)))))) (t (assert (not ok)) (unless (or (some #'thread-alive-p schedulers) (not (queue-empty-p q))) (return (list a ac b bc c cc d dc)))))))))) (let ((deschedulers (list (make-thread #'dq) (make-thread #'dq) (make-thread #'dq) (make-thread #'dq)))) (loop repeat 8 do (wait-on-semaphore r)) (signal-semaphore w 8) (let ((a -1) (ac 0) (b -1) (bc 0) (c -1) (cc 0) (d -1) (dc 0)) (mapc (lambda (th) (let ((results (join-thread th))) (when results (destructuring-bind (ta tac tb tbc tc tcc td tdc) results (setf a (max ta a) b (max tb b) c (max tc c) d (max td d)) (incf ac tac) (incf bc tbc) (incf cc tcc) (incf dc tdc))))) deschedulers) (assert (and (= n ac (1+ a)) (= n bc (1+ b)) (= n cc (1+ c)) (= n dc (1+ d)))))))) ;;;; Unix success convention for exit codes (sb-ext:quit :unix-status 0)