strict-io-0.1: Data/IORef/Strict.hs
--------------------------------------------------------------------
-- |
-- Module : Data.IORef.Strict
-- Copyright : (c) Nicolas Pouillard 2009
-- License : BSD3
--
-- Maintainer : Nicolas Pouillard <nicolas.pouillard@gmail.com>
-- Stability : provisional
--
-- Mutable references of strict values in the 'SIO' monad.
--
-- The type of references remains the same as in the 'IO' monad
-- and is just re-exported here.
--------------------------------------------------------------------
module Data.IORef.Strict
(IORef
,newIORef
,readIORef
,writeIORef
,modifyIORef
,atomicModifyIORef
,mkWeakIORef
)
where
import qualified System.IO.Strict.Internals as SIO
import System.IO.Strict.Internals (SIO(..))
import System.Mem.Weak (Weak)
import qualified Data.IORef as IO
import Data.IORef (IORef)
import Control.Parallel.Strategies (NFData(..))
-- | Build a new 'IORef', but force the value before storing it.
newIORef :: NFData sa => sa -> SIO (IORef sa)
newIORef value = rnf value `seq` SIO (IO.newIORef value)
-- | Read the value of an 'IORef'
readIORef :: IORef a -> SIO a
readIORef = SIO . IO.readIORef
-- | Deeply force a value and write it into an 'IORef'
writeIORef :: NFData sa => IORef sa -> sa -> SIO ()
writeIORef ref value = rnf value `seq` SIO $ IO.writeIORef ref value
-- | Mutate the contents of an 'IORef'
modifyIORef :: NFData sa => IORef sa -> (sa -> sa) -> SIO ()
modifyIORef ref f = readIORef ref >>= writeIORef ref . f
-- | Atomically modifies the contents of an 'IORef'.
--
-- This function is useful for using 'IORef' in a safe way in a multithreaded program.
-- If you only have one 'IORef', then using 'atomicModifyIORef' to access and modify
-- it will prevent race conditions.
--
-- Extending the atomicity to multiple 'IORef's is problematic, so it is recommended that
-- if you need to do anything more complicated then using "Control.Concurrent.MVar.MVar"
-- instead is a good idea.
atomicModifyIORef :: (NFData sa, NFData sb) => IORef sa -> (sa -> (sa, sb)) -> SIO sb
atomicModifyIORef ref f = SIO $ do x <- IO.atomicModifyIORef ref (rnf' . f)
rnf x `seq` return x
-- since the result of 'f' is a pair which has to forced
where rnf' x = rnf x `seq` x
-- | Make a 'Weak' pointer to an 'IORef'
mkWeakIORef :: IORef a -> SIO () -> SIO (Weak (IORef a))
mkWeakIORef ref (SIO finalizer) = SIO $ IO.mkWeakIORef ref finalizer