1 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; This software is derived from the CMU CL system, which was written at
5 ;;;; Carnegie Mellon University and released into the public domain. The
6 ;;;; software is in the public domain and is provided with absolutely no
7 ;;;; warranty. See the COPYING and CREDITS files for more information.
9 (in-package :sb-concurrency-test)
11 (deftest mailbox-trivia.1
12 (values (mailboxp (make-mailbox))
17 (deftest mailbox-trivia.2
18 (let ((mbox1 (make-mailbox :name "foof"))
19 (mbox2 (make-mailbox)))
20 (values (mailbox-name mbox1)
21 (mailbox-name mbox2)))
25 (deftest mailbox-trivia.3
26 (flet ((test (initial-contents)
27 (let ((mbox (make-mailbox :initial-contents initial-contents)))
28 (list (mailbox-count mbox)
29 (mailbox-empty-p mbox)
30 (list-mailbox-messages mbox)
31 (eq (list-mailbox-messages mbox) initial-contents)))))
32 (values (test '(1 2 3))
38 (3 nil (#\1 #\2 #\3) nil)
44 ;; Dummy struct for ATOMIC-INCF to work.
46 (ref 0 :type sb-vm:word))
48 (defun test-mailbox-producers-consumers
49 (&key n-senders n-receivers n-messages mailbox interruptor)
50 (let* ((cnt (make-counter))
51 (mbox (or mailbox (make-mailbox)))
53 (make-threads n-senders "SENDER"
55 (dotimes (i n-messages)
57 (sleep (random 0.001))))))
59 ;; We have three groups of receivers, one using
60 ;; RECEIVE-MESSAGE, one RECEIVE-MESSAGE-NO-HANG, and another
61 ;; one RECEIVE-PENDING-MESSAGES.
62 (let* ((aux (floor n-receivers 2))
63 (n-recv-msg (- n-receivers aux))
64 (n-recv-pend-msgs (floor aux 3))
65 (n-recv-msg-n-h (- aux n-recv-pend-msgs)))
67 (make-threads n-recv-msg "RECV-MSG"
69 (sleep (random 0.001))
72 (sb-sys:with-deadline (:seconds 1.0)
73 (let ((msg (receive-message mbox)))
74 (sb-ext:atomic-incf (counter-ref cnt))
75 (unless (< -1 msg n-messages)
77 (sb-ext:timeout ()))))
78 (make-threads n-recv-pend-msgs "RECV-PEND-MSGS"
80 (sleep (random 0.001))
83 (let ((msgs (receive-pending-messages mbox (random 5))))
85 (sb-ext:atomic-incf (counter-ref cnt))
86 (unless (< -1 msg n-messages)
89 (make-threads n-recv-msg-n-h "RECV-MSG-NO-HANG"
91 (sleep (random 0.001))
94 (multiple-value-bind (msg ok)
95 (receive-message-no-hang mbox)
97 (sb-ext:atomic-incf (counter-ref cnt))
98 (unless (< -1 msg n-messages)
100 (threads (append receivers senders)))
101 (when interruptor (funcall interruptor threads))
102 (mapc #'timed-join-thread threads)
103 (values mbox (counter-ref cnt) (* n-senders n-messages))))
105 (deftest mailbox.single-producer-single-consumer
106 (multiple-value-bind (mbox received total)
107 (test-mailbox-producers-consumers :n-senders 1
113 (list-mailbox-messages mbox)))
118 (deftest mailbox.single-producer-multiple-consumers
119 (multiple-value-bind (mbox received total)
120 (test-mailbox-producers-consumers :n-senders 1
126 (list-mailbox-messages mbox)))
131 (deftest mailbox.multiple-producers-single-consumer
132 (multiple-value-bind (mbox received total)
133 (test-mailbox-producers-consumers :n-senders 100
139 (list-mailbox-messages mbox)))
144 (deftest mailbox.multiple-producers-multiple-consumers
145 (multiple-value-bind (mbox received total)
146 (test-mailbox-producers-consumers :n-senders 100
152 (list-mailbox-messages mbox)))
157 (deftest mailbox.interrupts-safety.1
158 (multiple-value-bind (mbox received total)
159 (test-mailbox-producers-consumers
163 :interruptor #'(lambda (threads)
164 (let ((n (length threads)))
165 ;; 99 so even in the unlikely case that only
166 ;; receivers (or only senders) are shot
167 ;; dead, there's still one that survives to
168 ;; properly end the test.
170 (kill-thread (nth (random n) threads))))))
172 ;; We may have killed a receiver before it got to incrementing
176 (list-mailbox-messages mbox)))
181 ) ; #+sb-thread (progn ...