{-# LANGUAGE BangPatterns, ForeignFunctionInterface #-} -- | An atomic integer value. All operations are thread safe. module Data.Atomic ( Atomic , new , read , write , inc , dec , add , subtract ) where import Data.Int (Int64) import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtr, withForeignPtr) import Foreign.Ptr (Ptr) import Foreign.Storable (poke) import Prelude hiding (read, subtract) -- | A mutable, atomic integer. newtype Atomic = C (ForeignPtr Int64) -- | Create a new, zero initialized, atomic. new :: Int64 -> IO Atomic new n = do fp <- mallocForeignPtr withForeignPtr fp $ \ p -> poke p n return $ C fp read :: Atomic -> IO Int64 read (C fp) = withForeignPtr fp cRead foreign import ccall unsafe "hs_atomic_read" cRead :: Ptr Int64 -> IO Int64 -- | Set the atomic to the given value. write :: Atomic -> Int64 -> IO () write (C fp) n = withForeignPtr fp $ \ p -> cWrite p n foreign import ccall unsafe "hs_atomic_write" cWrite :: Ptr Int64 -> Int64 -> IO () -- | Increase the atomic by one. inc :: Atomic -> IO () inc atomic = add atomic 1 -- | Decrease the atomic by one. dec :: Atomic -> IO () dec atomic = subtract atomic 1 -- | Increase the atomic by the given amount. add :: Atomic -> Int64 -> IO () add (C fp) n = withForeignPtr fp $ \ p -> cAdd p n -- | Decrease the atomic by the given amount. subtract :: Atomic -> Int64 -> IO () subtract (C fp) n = withForeignPtr fp $ \ p -> cSubtract p n -- | Increase the atomic by the given amount. foreign import ccall unsafe "hs_atomic_add" cAdd :: Ptr Int64 -> Int64 -> IO () -- | Increase the atomic by the given amount. foreign import ccall unsafe "hs_atomic_subtract" cSubtract :: Ptr Int64 -> Int64 -> IO ()