reactor-0.1.3: Reactor/Atomic.hs
{-# LANGUAGE DeriveDataTypeable #-}
module Reactor.Atomic where
import Control.Monad
import Control.Monad.IO.Class
import Data.Bits.Atomic
import Data.Data
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Storable
import System.IO.Unsafe
newtype Atomic a = Atomic (ForeignPtr a)
deriving (Data, Typeable)
instance (Show a, Storable a) => Show (Atomic a) where
showsPrec d (Atomic fp) = showsPrec d $ unsafePerformIO $ withForeignPtr fp peek
atomic :: (MonadIO m, AtomicBits a, Storable a) => a -> m (Atomic a)
atomic a = liftIO $ do
fp <- mallocForeignPtr
withForeignPtr fp $ \p -> poke p a
return $ Atomic fp
withAtomic :: MonadIO m => Atomic a -> (Ptr a -> IO b) -> m b
withAtomic (Atomic fp) = liftIO . withForeignPtr fp
{-# INLINE withAtomic #-}
atomicFetchAndAdd :: (MonadIO m, AtomicBits a) => Atomic a -> a -> m a
atomicFetchAndAdd fp a = withAtomic fp $ \p -> fetchAndAdd p a
{-# INLINE atomicFetchAndAdd #-}
atomicFetchAndAnd :: (MonadIO m, AtomicBits a) => Atomic a -> a -> m a
atomicFetchAndAnd fp a = withAtomic fp $ \p -> fetchAndAnd p a
{-# INLINE atomicFetchAndAnd #-}
atomicFetch :: (MonadIO m, AtomicBits a) => Atomic a -> m a
atomicFetch fp = atomicFetchAndAdd fp 0
{-# INLINE atomicFetch #-}
atomicFetchAndSub :: (MonadIO m, AtomicBits a) => Atomic a -> a -> m a
atomicFetchAndSub fp a = withAtomic fp $ \p -> fetchAndSub p a
{-# INLINE atomicFetchAndSub #-}
atomicSubAndFetch :: (MonadIO m, AtomicBits a) => Atomic a -> a -> m a
atomicSubAndFetch fp a = withAtomic fp $ \p -> subAndFetch p a
{-# INLINE atomicSubAndFetch #-}
atomicAddAndFetch :: (MonadIO m, AtomicBits a) => Atomic a -> a -> m a
atomicAddAndFetch fp a = withAtomic fp $ \p -> subAndFetch p a
{-# INLINE atomicAddAndFetch #-}
atomicCompareAndSwapBool :: (MonadIO m, AtomicBits a) => Atomic a -> a -> a -> m Bool
atomicCompareAndSwapBool fp old new = withAtomic fp $ \p -> compareAndSwapBool p old new
{-# INLINE atomicCompareAndSwapBool #-}
atomicCompareAndSwap :: (MonadIO m, AtomicBits a) => Atomic a -> a -> a -> m a
atomicCompareAndSwap fp old new = withAtomic fp $ \p -> compareAndSwap p old new
{-# INLINE atomicCompareAndSwap #-}
atomicLockTestAndSet :: (MonadIO m, AtomicBits a) => Atomic a -> m a
atomicLockTestAndSet fp = withAtomic fp lockTestAndSet
{-# INLINE atomicLockTestAndSet #-}
atomicLockRelease :: (MonadIO m, AtomicBits a) => Atomic a -> m ()
atomicLockRelease fp = withAtomic fp lockRelease
{-# INLINE atomicLockRelease #-}
given :: (MonadIO m, AtomicBits a) => Atomic a -> m () -> m ()
given flag task = do
i <- atomicFetch flag
when (i /= 0) task
clearing :: (MonadIO m, AtomicBits a) => Atomic a -> m () -> m ()
clearing flag task = do
i <- atomicFetchAndAnd flag 0
when (i /= 0) task