{-# LANGUAGE MagicHash, UnboxedTuples, BangPatterns, TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses #-} module Data.Ref.CAS where import GHC.IO import GHC.IORef import GHC.Prim import GHC.ST import GHC.STRef {- the following code is due to Adam Foltzer , under a BSD3 license and orignated from https://github.com/rrnewton/haskell-lockfree-queue/blob/master/CAS/ NOTE also that -} -- | Performs a machine-level compare and swap operation on an -- 'STRef'. Returns a tuple containing a 'Bool' which is 'True' when a -- swap is performed, along with the 'current' value from the 'STRef'. -- -- Note \"compare\" here means pointer equality in the sense of -- 'GHC.Prim.reallyUnsafePtrEquality#'. casSTRef :: STRef s a -- ^ The 'STRef' containing a value 'current' -> a -- ^ The 'old' value to compare -> a -- ^ The 'new' value to replace 'current' if @old == current@ -> ST s (Bool, a) casSTRef (STRef var#) !old !new = ST $ \s1# -> -- The primop treats the boolean as a sort of error code. -- Zero means the CAS worked, one that it didn't. -- We flip that here: case casMutVar# var# old new s1# of (# s2#, x#, res #) -> (# s2#, (x# ==# 0#, res) #) -- | Performs a machine-level compare and swap operation on an -- 'IORef'. Returns a tuple containing a 'Bool' which is 'True' when a -- swap is performed, along with the 'current' value from the 'IORef'. -- -- Note \"compare\" here means pointer equality in the sense of -- 'GHC.Prim.reallyUnsafePtrEquality#'. casIORef :: IORef a -- ^ The 'IORef' containing a value 'current' -> a -- ^ The 'old' value to compare -> a -- ^ The 'new' value to replace 'current' if @old == current@ -> IO (Bool, a) casIORef (IORef var) !old !new = stToIO (casSTRef var old new)