5 (macrolet ((test (init op)
9 (assert (eql nil (compare-and-swap (,op x) nil y)))
10 (assert (eql y (compare-and-swap (,op x) nil z)))
11 (assert (eql y (,op x)))
13 (multiple-value-bind (res err)
14 (ignore-errors (compare-and-swap (,op x) nil nil))
16 (assert (typep err 'type-error)))))))
17 (test (cons nil :no) car)
18 (test (cons nil :no) first)
19 (test (cons :no nil) cdr)
20 (test (cons :no nil) rest)
21 (test '.foo. symbol-plist)
22 (test (progn (set '.bar. nil) '.bar.) symbol-value)
23 (test (make-xxx) xxx-yyy))
27 ;;; thread-local bindings
31 (assert (eql nil (compare-and-swap (symbol-value '*foo*) nil t)))
32 (assert (eql t (compare-and-swap (symbol-value '*foo*) nil :foo)))
33 (assert (eql t *foo*)))
34 (assert (eql 42 *foo*)))
36 ;;; unbound symbols + symbol-value
38 (assert (not (boundp '*foo*)))
40 (multiple-value-bind (res err)
41 (ignore-errors (compare-and-swap (symbol-value '*foo*) nil t))
43 (assert (typep err 'unbound-variable)))
49 (multiple-value-bind (res err)
50 (ignore-errors (compare-and-swap (symbol-value '*bar*) nil t))
52 (assert (typep err 'unbound-variable))))
56 (defvar *v* (vector 1))
59 (assert (eql 1 (compare-and-swap (svref *v* 0) 1 2)))
60 (assert (eql 2 (compare-and-swap (svref *v* 0) 1 3)))
61 (assert (eql 2 (svref *v* 0)))
64 (multiple-value-bind (res err)
65 (ignore-errors (compare-and-swap (svref *v* -1) 1 2))
67 (assert (typep err 'type-error)))
68 (multiple-value-bind (res err)
69 (ignore-errors (compare-and-swap (svref *v* 1) 1 2))
71 (assert (typep err 'type-error)))
73 ;; type of the first argument
74 (multiple-value-bind (res err)
75 (ignore-errors (compare-and-swap (svref "foo" 1) 1 2))
77 (assert (typep err 'type-error)))
79 ;; Check that we don't modify constants
80 (defconstant +a-constant+ 42)
84 (sb-ext:compare-and-swap (symbol-value '+a-constant+) 42 13)
86 (let ((name '+a-constant+))
90 (sb-ext:compare-and-swap (symbol-value name) 42 13)
93 ;; Check that we don't mess declaimed types
94 (declaim (boolean *a-boolean*))
95 (defparameter *a-boolean* t)
99 (sb-ext:compare-and-swap (symbol-value '*a-boolean*) t 42)
101 (let ((name '*a-boolean*))
105 (sb-ext:compare-and-swap (symbol-value name) t 42)
106 (error () :error)))))
108 ;;;; ATOMIC-INCF and ATOMIC-DECF (we should probably rename this file atomic-ops...)
111 (word 0 :type sb-vm:word))
113 (defun inc-box (box n)
114 (declare (fixnum n) (box box))
116 do (sb-ext:atomic-incf (box-word box))))
118 (defun dec-box (box n)
119 (declare (fixnum n) (box box))
121 do (sb-ext:atomic-decf (box-word box))))
123 (let ((box (make-box)))
125 (assert (= 10000 (box-word box)))
127 (assert (= 0 (box-word box))))
129 (with-test (:name :atomic-incf-wraparound)
130 (let ((box (make-box :word (1- (ash 1 sb-vm:n-word-bits)))))
131 (sb-ext:atomic-incf (box-word box) 2)
132 (assert (= 1 (box-word box)))))
134 (with-test (:name :atomic-decf-wraparound)
135 (let ((box (make-box :word 0)))
136 (sb-ext:atomic-decf (box-word box) 2)
137 (assert (= (- (ash 1 sb-vm:n-word-bits) 2) (box-word box)))))
140 (let* ((box (make-box))
141 (threads (loop repeat 64
142 collect (sb-thread:make-thread (lambda ()
147 :name "inc/dec thread"))))
148 (mapc #'sb-thread:join-thread threads)
149 (assert (= 0 (box-word box))))