Luís Oliveira recently published a blog post (http://kvardek-du.kerno.org/2012/06/augmenting-bordeaux-threads-with-atomic....) iscussing the possibility of extending BT with atomic operations (like compare-and-swap). He put together a very handy table about implementation support for this operation, which gives the impression that it might indeed be a good time to wrap this feature in a portable API.
I'm working on a library that happens to use compare-and-swap, and wrote the following macro:
(defmacro compare-and-swap (place old-value new-value) #+sbcl (let ((old-val-var (gensym "OLD-VALUE-"))) ` (let ((,old-val-var ,old-value)) (eq ,old-val-var (sb-ext:compare-and-swap ,place ,old-val-var ,new-value)))) #+ccl `(ccl::conditional-store ,place ,old-value ,new-value) #+lispworks `(system:compare-and-swap ,place ,old-value ,new-value) #+allegro `(excl:atomic-conditional-setf ,place ,new-value ,old-value) #-(or allegro lispworks ccl sbcl) `(error "Not supported."))
I've tested this in all the mentioned implementations. I'm considering putting together a patch to add this macro to BT itself, and I'd like to know if this would be wanted, if there's any issues with the API itself, etc.
There are two big issues I see:
1. On CCL, conditional-store is an internal, unexported operation. It's also pretty narrow in what it can handle, and even breaks in situations such as typed struct slot access. rme was kind enough to create a ticket for this on the Clozure CL tracker, so this issue may be resolved in the (near?) future: http://trac.clozure.com/ccl/ticket/994
2. CAS support across implementations has a lot of 'but's associated with it. The only thing that seems to be supported across the listed implementations is svref and struct access. There's also weird behavior on some implementations (notably SBCL) when it comes to accessing dynamic variables (where it can only access the global binding, not the local one). Is this acceptable? Should a patch include compile-time warnings or errors when we detect (when possible) that CAS is being used on an unsupported place? Should it be left up to users to use it in the right case? Should it break for anything other than svref and structslot, which are the only ones supported across the board?
-- Josh Marchán