{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE UndecidableInstances #-} -- | -- Module : Data.Prim.Atom -- Copyright : (c) Alexey Kuleshevich 2020 -- License : BSD3 -- Maintainer : Alexey Kuleshevich -- Stability : experimental -- Portability : non-portable -- module Data.Prim.Atom ( Atom(..) -- * SpinLocks , acquireLockByteOffMutableByteArray , releaseLockByteOffMutableByteArray , acquireLockByteOffAddr , releaseLockByteOffAddr -- ** Expirimental , withLockMutableByteArray , withLockOffAddr -- * Helpers and testing -- -- Functions below are used for implementing `Atom` instances and are useful for -- testing other types as well as defining potential cusom instances -- ** Count , atomicAddFetchOldMutableByteArrayNum# , atomicAddFetchNewMutableByteArrayNum# , atomicSubFetchOldMutableByteArrayNum# , atomicSubFetchNewMutableByteArrayNum# , atomicAddFetchOldOffAddrNum# , atomicAddFetchNewOffAddrNum# , atomicSubFetchOldOffAddrNum# , atomicSubFetchNewOffAddrNum# -- ** Bits , atomicAndFetchOldMutableByteArrayBits# , atomicAndFetchNewMutableByteArrayBits# , atomicNandFetchOldMutableByteArrayBits# , atomicNandFetchNewMutableByteArrayBits# , atomicOrFetchOldMutableByteArrayBits# , atomicOrFetchNewMutableByteArrayBits# , atomicXorFetchOldMutableByteArrayBits# , atomicXorFetchNewMutableByteArrayBits# , atomicAndFetchOldOffAddrBits# , atomicAndFetchNewOffAddrBits# , atomicNandFetchOldOffAddrBits# , atomicNandFetchNewOffAddrBits# , atomicOrFetchOldOffAddrBits# , atomicOrFetchNewOffAddrBits# , atomicXorFetchOldOffAddrBits# , atomicXorFetchNewOffAddrBits# ) where import Control.DeepSeq import Control.Exception import Control.Monad import Control.Prim.Monad import Control.Prim.Monad.Unsafe import Data.Bits import Data.Prim.Atomic import Data.Prim.Class import Foreign.Prim hiding (Any) import GHC.IO import GHC.TypeLits newtype Atom a = Atom { unAtom :: a } deriving (Show, Eq, Ord, Num, Enum, Integral, Real, RealFrac, Fractional, Floating, RealFloat, Bits, NFData) instance Prim a => Prim (Atom a) where type PrimBase (Atom a) = Atom a type SizeOf (Atom a) = 1 + SizeOf a type Alignment (Atom a) = 1 + Alignment a sizeOf# _ = 1# +# sizeOf# (proxy# :: Proxy# a) {-# INLINE sizeOf# #-} alignment# _ = 1# +# alignment# (proxy# :: Proxy# a) {-# INLINE alignment# #-} indexByteOffByteArray# ba# i# = Atom (indexByteOffByteArray# ba# (1# +# i#)) {-# INLINE indexByteOffByteArray# #-} indexByteArray# ba# i# = indexByteOffByteArray# ba# (i# *# sizeOf# (proxy# :: Proxy# (Atom a))) {-# INLINE indexByteArray# #-} indexOffAddr# addr# i# = Atom (indexOffAddr# (addr# `plusAddr#` (1# +# i# *# sizeOf# (proxy# :: Proxy# (Atom a)))) 0#) {-# INLINE indexOffAddr# #-} readByteOffMutableByteArray# mba# i# s = case readByteOffMutableByteArray# mba# (1# +# i#) s of (# s', a #) -> (# s', Atom a #) {-# INLINE readByteOffMutableByteArray# #-} readMutableByteArray# mba# i# = readByteOffMutableByteArray# mba# (i# *# sizeOf# (proxy# :: Proxy# (Atom a))) {-# INLINE readMutableByteArray# #-} readOffAddr# addr# i# s = case readOffAddr# (addr# `plusAddr#` (1# +# i# *# sizeOf# (proxy# :: Proxy# (Atom a)))) 0# s of (# s', a #) -> (# s', Atom a #) {-# INLINE readOffAddr# #-} writeByteOffMutableByteArray# mba# i# (Atom a) s = writeByteOffMutableByteArray# mba# i# (0 :: Word8) (writeByteOffMutableByteArray# mba# (1# +# i#) a s) {-# INLINE writeByteOffMutableByteArray# #-} writeMutableByteArray# mba# i# (Atom a) s = let i0# = i# *# sizeOf# (proxy# :: Proxy# (Atom a)) in writeByteOffMutableByteArray# mba# i0# (0 :: Word8) (writeByteOffMutableByteArray# mba# (1# +# i0#) a s) {-# INLINE writeMutableByteArray# #-} writeOffAddr# addr# i# (Atom a) s = let i0# = i# *# sizeOf# (proxy# :: Proxy# (Atom a)) in writeOffAddr# addr# i0# (0 :: Word8) (writeOffAddr# (addr# `plusAddr#` (1# +# i0#)) 0# a s) {-# INLINE writeOffAddr# #-} setMutableByteArray# = setMutableByteArrayLoop# {-# INLINE setMutableByteArray# #-} setOffAddr# = setOffAddrLoop# {-# INLINE setOffAddr# #-} acquireLockByteOffMutableByteArray :: MutableByteArray# RealWorld -> Int# -> IO () acquireLockByteOffMutableByteArray mba# i# = let go = do locked <- syncLockTestSetInt8ArrayIO mba# i# when (locked == 0) go in go {-# INLINE acquireLockByteOffMutableByteArray #-} releaseLockByteOffMutableByteArray :: MutableByteArray# RealWorld -> Int# -> IO () releaseLockByteOffMutableByteArray mba# i# = syncLockReleaseInt8ArrayIO mba# i# {-# INLINE releaseLockByteOffMutableByteArray #-} acquireLockByteOffAddr :: Addr# -> Int# -> IO () acquireLockByteOffAddr addr# i# = let go = do locked <- syncLockTestSetInt8AddrIO addr# i# when (locked == 0) go in go {-# INLINE acquireLockByteOffAddr #-} releaseLockByteOffAddr :: Addr#-> Int# -> IO () releaseLockByteOffAddr addr# i# = syncLockReleaseInt8AddrIO addr# i# {-# INLINE releaseLockByteOffAddr #-} withLockMutableByteArray :: forall e b. Prim e => MutableByteArray# RealWorld -> Int# -> (Atom e -> IO (Atom e, b)) -> IO b withLockMutableByteArray mba# i# f = let li# = i# *# sizeOf# (proxy# :: Proxy# (Atom e)) in bracket_ (unsafeUnmask (acquireLockByteOffMutableByteArray mba# li#)) (releaseLockByteOffMutableByteArray mba# li#) $ IO $ \s -> case readMutableByteArray# mba# i# s of (# s', a #) -> case f a of IO m -> case m s' of (# s'', (a', b) #) -> (# writeMutableByteArray# mba# i# a' s'', b #) {-# INLINABLE withLockMutableByteArray #-} -- | Atomic reads on `Atom` require a lock because otherwise any other thread can -- overwrite the contnts in the midst of reading, resulting in a value with contents -- from both values part before and part after the write. atomicReadAtomMutableByteArray :: forall e. Prim e => MutableByteArray# RealWorld -> Int# -> IO (Atom e) atomicReadAtomMutableByteArray mba# i# = let li# = i# *# sizeOf# (proxy# :: Proxy# (Atom e)) in bracket_ (unsafeUnmask (acquireLockByteOffMutableByteArray mba# li#)) (releaseLockByteOffMutableByteArray mba# li#) (coerce (IO (readByteOffMutableByteArray# mba# (1# +# li#)) :: IO e)) {-# INLINABLE atomicReadAtomMutableByteArray #-} -- | Values are no longer guaranteed to be one word in size, as such in order for writes -- to be atomic we require locking. atomicWriteAtomMutableByteArray :: forall e. Prim e => MutableByteArray# RealWorld -> Int# -> Atom e -> IO () atomicWriteAtomMutableByteArray mba# i# (Atom a) = let li# = i# *# sizeOf# (proxy# :: Proxy# (Atom e)) in bracket_ (unsafeUnmask (acquireLockByteOffMutableByteArray mba# li#)) (releaseLockByteOffMutableByteArray mba# li#) (prim_ (writeByteOffMutableByteArray# mba# (1# +# li#) a)) {-# INLINABLE atomicWriteAtomMutableByteArray #-} -- | Same as `atomicReadAtomMutableByteArray`, but for `Addr#` with offset atomicReadAtomOffAddr :: forall e. Prim e => Addr# -> Int# -> IO (Atom e) atomicReadAtomOffAddr mba# i# = let li# = i# *# sizeOf# (proxy# :: Proxy# (Atom e)) in bracket_ (unsafeUnmask (acquireLockByteOffAddr mba# li#)) (releaseLockByteOffAddr mba# li#) (coerce (IO (readOffAddr# mba# (1# +# li#)) :: IO e)) {-# INLINABLE atomicReadAtomOffAddr #-} -- | Same as `atomicWriteAtomMutableByteArray`, but for `Addr#` with offset atomicWriteAtomOffAddr :: forall e. Prim e => Addr# -> Int# -> Atom e -> IO () atomicWriteAtomOffAddr mba# i# (Atom a) = let li# = i# *# sizeOf# (proxy# :: Proxy# (Atom e)) in bracket_ (unsafeUnmask (acquireLockByteOffAddr mba# li#)) (releaseLockByteOffAddr mba# li#) (prim_ (writeOffAddr# mba# (1# +# li#) a)) {-# INLINABLE atomicWriteAtomOffAddr #-} withLockOffAddr :: forall e b. Prim e => Addr# -> Int# -> (Atom e -> IO (Atom e, b)) -> IO b withLockOffAddr addr# i# f = let li# = i# *# sizeOf# (proxy# :: Proxy# (Atom e)) in bracket_ (unsafeUnmask (acquireLockByteOffAddr addr# li#)) (releaseLockByteOffAddr addr# li#) $ IO $ \s -> case readOffAddr# addr# i# s of (# s', a #) -> case f a of IO m -> case m s' of (# s'', (a', b) #) -> (# writeOffAddr# addr# i# a' s'', b #) {-# INLINABLE withLockOffAddr #-} atomicModifyAtomMutableByteArray# :: forall e b s. Prim e => MutableByteArray# s -> Int# -> (Atom e -> (# Atom e, b #)) -> State# s -> (# State# s, b #) atomicModifyAtomMutableByteArray# mba# i# f = let li# = i# *# sizeOf# (proxy# :: Proxy# (Atom e)) mba'# = unsafeCoerce# mba# :: MutableByteArray# RealWorld in unsafePrimBase $ bracket_ (unsafeUnmask (acquireLockByteOffMutableByteArray mba'# li#)) (releaseLockByteOffMutableByteArray mba'# li#) $ IO $ \s -> case readMutableByteArray# mba'# i# s of (# s', a #) -> case f a of (# a', b #) -> (# writeMutableByteArray# mba'# i# a' s', b #) {-# INLINE atomicModifyAtomMutableByteArray# #-} atomicModifyAtomOffAddr# :: forall e b s. Prim e => Addr# -> Int# -> (Atom e -> (# Atom e, b #)) -> State# s -> (# State# s, b #) atomicModifyAtomOffAddr# addr# i# f = let li# = i# *# sizeOf# (proxy# :: Proxy# (Atom e)) in unsafePrimBase $ bracket_ (unsafeUnmask (acquireLockByteOffAddr addr# li#)) (releaseLockByteOffAddr addr# li#) $ IO $ \s -> case readOffAddr# addr# i# s of (# s', a #) -> case f a of (# a', b #) -> (# writeOffAddr# addr# i# a' s', b #) {-# INLINE atomicModifyAtomOffAddr# #-} swapIfEqualVal :: Eq e => Atom e -> Atom e -> Atom e -> (# Atom e, Atom e #) swapIfEqualVal expected new actual | expected == actual = (# new, actual #) | otherwise = (# actual, actual #) {-# INLINE swapIfEqualVal #-} swapIfEqualBool :: Eq e => Atom e -> Atom e -> Atom e -> (# Atom e, Bool #) swapIfEqualBool expected new actual | expected == actual = (# new, True #) | otherwise = (# actual, False #) {-# INLINE swapIfEqualBool #-} instance (Eq a, Prim a) => Atomic (Atom a) where atomicReadMutableByteArray# mba# i# = unsafePrimBase (atomicReadAtomMutableByteArray (unsafeCoerce# mba#) i#) {-# INLINABLE atomicReadMutableByteArray# #-} atomicWriteMutableByteArray# mba# i# a = unsafePrimBase_ (atomicWriteAtomMutableByteArray (unsafeCoerce# mba#) i# a) {-# INLINABLE atomicWriteMutableByteArray# #-} atomicReadOffAddr# addr# i# = unsafePrimBase (atomicReadAtomOffAddr addr# i#) {-# INLINABLE atomicReadOffAddr# #-} atomicWriteOffAddr# addr# i# a = unsafePrimBase_ (atomicWriteAtomOffAddr addr# i# a) {-# INLINABLE atomicWriteOffAddr# #-} casMutableByteArray# mba# i# old new = atomicModifyAtomMutableByteArray# mba# i# (swapIfEqualVal old new) {-# INLINE casMutableByteArray# #-} casOffAddr# addr# i# old new = atomicModifyOffAddr# addr# i# (swapIfEqualVal old new) {-# INLINE casOffAddr# #-} casBoolMutableByteArray# mba# i# old new = atomicModifyAtomMutableByteArray# mba# i# (swapIfEqualBool old new) {-# INLINE casBoolMutableByteArray# #-} casBoolOffAddr# addr# i# old new = atomicModifyOffAddr# addr# i# (swapIfEqualBool old new) {-# INLINE casBoolOffAddr# #-} atomicModifyMutableByteArray# = atomicModifyAtomMutableByteArray# {-# INLINE atomicModifyMutableByteArray# #-} atomicModifyOffAddr# = atomicModifyAtomOffAddr# {-# INLINE atomicModifyOffAddr# #-} atomicAddFetchOldMutableByteArrayNum# , atomicAddFetchNewMutableByteArrayNum# , atomicSubFetchOldMutableByteArrayNum# , atomicSubFetchNewMutableByteArrayNum# :: (Num a, Atomic a) => MutableByteArray# s -> Int# -> a -> State# s -> (# State# s, a #) atomicAddFetchOldMutableByteArrayNum# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> (# x + y, x #)) {-# INLINE atomicAddFetchOldMutableByteArrayNum# #-} atomicAddFetchNewMutableByteArrayNum# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> let x' = x + y in (# x', x' #)) {-# INLINE atomicAddFetchNewMutableByteArrayNum# #-} atomicSubFetchOldMutableByteArrayNum# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> (# x - y, x #)) {-# INLINE atomicSubFetchOldMutableByteArrayNum# #-} atomicSubFetchNewMutableByteArrayNum# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> let x' = x - y in (# x', x' #)) {-# INLINE atomicSubFetchNewMutableByteArrayNum# #-} atomicAddFetchOldOffAddrNum# , atomicAddFetchNewOffAddrNum# , atomicSubFetchOldOffAddrNum# , atomicSubFetchNewOffAddrNum# :: (Num a, Atomic a) => Addr# -> Int# -> a -> State# s -> (# State# s, a #) atomicAddFetchOldOffAddrNum# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> (# x + y, x #)) {-# INLINE atomicAddFetchOldOffAddrNum# #-} atomicAddFetchNewOffAddrNum# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> let x' = x + y in (# x', x' #)) {-# INLINE atomicAddFetchNewOffAddrNum# #-} atomicSubFetchOldOffAddrNum# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> (# x - y, x #)) {-# INLINE atomicSubFetchOldOffAddrNum# #-} atomicSubFetchNewOffAddrNum# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> let x' = x - y in (# x', x' #)) {-# INLINE atomicSubFetchNewOffAddrNum# #-} instance (Num a, Eq a, Prim a) => AtomicCount (Atom a) where atomicAddFetchOldMutableByteArray# = atomicAddFetchOldMutableByteArrayNum# {-# INLINE atomicAddFetchOldMutableByteArray# #-} atomicAddFetchNewMutableByteArray# = atomicAddFetchNewMutableByteArrayNum# {-# INLINE atomicAddFetchNewMutableByteArray# #-} atomicSubFetchOldMutableByteArray# = atomicSubFetchOldMutableByteArrayNum# {-# INLINE atomicSubFetchOldMutableByteArray# #-} atomicSubFetchNewMutableByteArray# = atomicSubFetchNewMutableByteArrayNum# {-# INLINE atomicSubFetchNewMutableByteArray# #-} atomicAddFetchOldOffAddr# = atomicAddFetchOldOffAddrNum# {-# INLINE atomicAddFetchOldOffAddr# #-} atomicAddFetchNewOffAddr# = atomicAddFetchNewOffAddrNum# {-# INLINE atomicAddFetchNewOffAddr# #-} atomicSubFetchOldOffAddr# = atomicSubFetchOldOffAddrNum# {-# INLINE atomicSubFetchOldOffAddr# #-} atomicSubFetchNewOffAddr# = atomicSubFetchNewOffAddrNum# {-# INLINE atomicSubFetchNewOffAddr# #-} atomicAndFetchOldMutableByteArrayBits# , atomicAndFetchNewMutableByteArrayBits# , atomicNandFetchOldMutableByteArrayBits# , atomicNandFetchNewMutableByteArrayBits# , atomicOrFetchOldMutableByteArrayBits# , atomicOrFetchNewMutableByteArrayBits# , atomicXorFetchOldMutableByteArrayBits# , atomicXorFetchNewMutableByteArrayBits# :: (Bits a, Atomic a) => MutableByteArray# s -> Int# -> a -> State# s -> (# State# s, a #) atomicAndFetchOldMutableByteArrayBits# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> (# x .&. y, x #)) {-# INLINE atomicAndFetchOldMutableByteArrayBits# #-} atomicAndFetchNewMutableByteArrayBits# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> let x' = x .&. y in (# x', x' #)) {-# INLINE atomicAndFetchNewMutableByteArrayBits# #-} atomicNandFetchOldMutableByteArrayBits# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> (# complement (x .&. y), x #)) {-# INLINE atomicNandFetchOldMutableByteArrayBits# #-} atomicNandFetchNewMutableByteArrayBits# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> let x' = complement (x .&. y) in (# x', x' #)) {-# INLINE atomicNandFetchNewMutableByteArrayBits# #-} atomicOrFetchOldMutableByteArrayBits# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> (# x .|. y, x #)) {-# INLINE atomicOrFetchOldMutableByteArrayBits# #-} atomicOrFetchNewMutableByteArrayBits# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> let x' = x .|. y in (# x', x' #)) {-# INLINE atomicOrFetchNewMutableByteArrayBits# #-} atomicXorFetchOldMutableByteArrayBits# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> (# x `xor` y, x #)) {-# INLINE atomicXorFetchOldMutableByteArrayBits# #-} atomicXorFetchNewMutableByteArrayBits# mba# i# y = atomicModifyMutableByteArray# mba# i# (\x -> let x' = x `xor` y in (# x', x' #)) {-# INLINE atomicXorFetchNewMutableByteArrayBits# #-} atomicAndFetchOldOffAddrBits# , atomicAndFetchNewOffAddrBits# , atomicNandFetchOldOffAddrBits# , atomicNandFetchNewOffAddrBits# , atomicOrFetchOldOffAddrBits# , atomicOrFetchNewOffAddrBits# , atomicXorFetchOldOffAddrBits# , atomicXorFetchNewOffAddrBits# :: (Bits a, Atomic a) => Addr# -> Int# -> a -> State# s -> (# State# s, a #) atomicAndFetchOldOffAddrBits# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> (# x .&. y, x #)) {-# INLINE atomicAndFetchOldOffAddrBits# #-} atomicAndFetchNewOffAddrBits# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> let x' = x .&. y in (# x', x' #)) {-# INLINE atomicAndFetchNewOffAddrBits# #-} atomicNandFetchOldOffAddrBits# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> (# complement (x .&. y), x #)) {-# INLINE atomicNandFetchOldOffAddrBits# #-} atomicNandFetchNewOffAddrBits# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> let x' = complement (x .&. y) in (# x', x' #)) {-# INLINE atomicNandFetchNewOffAddrBits# #-} atomicOrFetchOldOffAddrBits# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> (# x .|. y, x #)) {-# INLINE atomicOrFetchOldOffAddrBits# #-} atomicOrFetchNewOffAddrBits# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> let x' = x .|. y in (# x', x' #)) {-# INLINE atomicOrFetchNewOffAddrBits# #-} atomicXorFetchOldOffAddrBits# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> (# x `xor` y, x #)) {-# INLINE atomicXorFetchOldOffAddrBits# #-} atomicXorFetchNewOffAddrBits# addr# i# y = atomicModifyOffAddr# addr# i# (\x -> let x' = x `xor` y in (# x', x' #)) {-# INLINE atomicXorFetchNewOffAddrBits# #-} instance (Bits a, Eq a, Prim a) => AtomicBits (Atom a) where atomicAndFetchOldMutableByteArray# = atomicAndFetchOldMutableByteArrayBits# {-# INLINE atomicAndFetchOldMutableByteArray# #-} atomicAndFetchNewMutableByteArray# = atomicAndFetchNewMutableByteArrayBits# {-# INLINE atomicAndFetchNewMutableByteArray# #-} atomicNandFetchOldMutableByteArray# = atomicNandFetchOldMutableByteArrayBits# {-# INLINE atomicNandFetchOldMutableByteArray# #-} atomicNandFetchNewMutableByteArray# = atomicNandFetchNewMutableByteArrayBits# {-# INLINE atomicNandFetchNewMutableByteArray# #-} atomicOrFetchOldMutableByteArray# = atomicOrFetchOldMutableByteArrayBits# {-# INLINE atomicOrFetchOldMutableByteArray# #-} atomicOrFetchNewMutableByteArray# = atomicOrFetchNewMutableByteArrayBits# {-# INLINE atomicOrFetchNewMutableByteArray# #-} atomicXorFetchOldMutableByteArray# = atomicXorFetchOldMutableByteArrayBits# {-# INLINE atomicXorFetchOldMutableByteArray# #-} atomicXorFetchNewMutableByteArray# = atomicXorFetchNewMutableByteArrayBits# {-# INLINE atomicXorFetchNewMutableByteArray# #-} atomicAndFetchOldOffAddr# = atomicAndFetchOldOffAddrBits# {-# INLINE atomicAndFetchOldOffAddr# #-} atomicAndFetchNewOffAddr# = atomicAndFetchNewOffAddrBits# {-# INLINE atomicAndFetchNewOffAddr# #-} atomicNandFetchOldOffAddr# = atomicNandFetchOldOffAddrBits# {-# INLINE atomicNandFetchOldOffAddr# #-} atomicNandFetchNewOffAddr# = atomicNandFetchNewOffAddrBits# {-# INLINE atomicNandFetchNewOffAddr# #-} atomicOrFetchOldOffAddr# = atomicOrFetchOldOffAddrBits# {-# INLINE atomicOrFetchOldOffAddr# #-} atomicOrFetchNewOffAddr# = atomicOrFetchNewOffAddrBits# {-# INLINE atomicOrFetchNewOffAddr# #-} atomicXorFetchOldOffAddr# = atomicXorFetchOldOffAddrBits# {-# INLINE atomicXorFetchOldOffAddr# #-} atomicXorFetchNewOffAddr# = atomicXorFetchNewOffAddrBits# {-# INLINE atomicXorFetchNewOffAddr# #-}