{-# LANGUAGE ForeignFunctionInterface #-} module System.Posix.AtomicOps ( -- * types FPRef -- * basic interface , newFPRef , readFPRef , writeFPRef -- * FPRef Int operations , fetchAddFPRef , addFetchFPRef ) where import Foreign.C.Types import Foreign.ForeignPtr import Foreign.Ptr import Foreign.Storable -- | A reference to a value held in a Foreign Ptr newtype FPRef a = FPRef { unFPRef :: ForeignPtr a } foreign import ccall unsafe "fetch_add_int64" c_fetch_add :: Ptr CInt -> CInt -> IO CInt foreign import ccall unsafe "add_fetch_int64" c_add_fetch :: Ptr CInt -> CInt -> IO CInt newFPRef :: Storable a => a -> IO (FPRef a) newFPRef a = do fp <- mallocForeignPtr withForeignPtr fp (flip poke a) return $ FPRef fp readFPRef :: Storable a => FPRef a -> IO a readFPRef (FPRef fp) = withForeignPtr fp peek writeFPRef :: Storable a => FPRef a -> a -> IO () writeFPRef (FPRef fp) a = withForeignPtr fp (flip poke a) -- | fetch the previous value in an 'FPRef', and increment the FPRef by the given -- amount. This operation is atomic. fetchAddFPRef :: FPRef Int -> Int -> IO Int fetchAddFPRef (FPRef fp) incr = withForeignPtr fp $ \p -> fromIntegral `fmap` c_fetch_add (castPtr p) (fromIntegral incr) -- | increment the FPRef by the given amount and return the new value. This operation is atomic. addFetchFPRef :: FPRef Int -> Int -> IO Int addFetchFPRef (FPRef fp) incr = withForeignPtr fp $ \p -> fromIntegral `fmap` c_add_fetch (castPtr p) (fromIntegral incr)