'Atomic Operations for Multithreading in SBCL
I'm getting an error when loading a function that contains an atomic operation. As a simple example, the file test.lisp contains:
(defparameter *count* 0)
(defun test ()
  (sb-ext:atomic-incf *count*))
which generates the following error:
* (load "d:\\test.lisp")
; file: d:/test.lisp
; in: DEFUN TEST
;     (ATOMIC-INCF *COUNT*)
;
; caught ERROR:
;   during macroexpansion of (ATOMIC-INCF *COUNT*). Use *BREAK-ON-SIGNALS* to
;   intercept.
;
;    Invalid first argument to ATOMIC-INCF: *COUNT*
;
; compilation unit finished
;   caught 1 ERROR condition
T
*
Why is *count* invalid?
Solution 1:[1]
From the docstring:
PLACE must access one of the following:
 - a DEFSTRUCT slot with declared type (UNSIGNED-BYTE 64)
   or AREF of a (SIMPLE-ARRAY (UNSIGNED-BYTE 64) (*))
   The type SB-EXT:WORD can be used for these purposes.
 - CAR or CDR (respectively FIRST or REST) of a CONS.
 - a variable defined using DEFGLOBAL with a proclaimed type of FIXNUM.
Macroexpansion is performed on PLACE before expanding ATOMIC-INCF.
I suspect these are in place to avoid runtime checks when doing compare-and-swap.
Solution 2:[2]
To answer a question from above about how to use atomic-incf with a proclaimed global variable as a fixnum, this is what worked for me:
(declaim (fixnum **var**))
(sb-ext:defglobal **var** 0)
(sb-ext:atomic-incf **var**)
Solution 3:[3]
(defparameter *count* (list 0))
(defun test ()
   (sb-ext:atomic-incf (car *count*)))
(test)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | Xach | 
| Solution 2 | Tyler | 
| Solution 3 | hxz_rx | 
