-- | This module extends "Data.IORef" with operations forcing the value written to the IORef.
--   Some of these functions are available in later versions of GHC, but not all.
module Data.IORef.Extra(
    module Data.IORef,
    writeIORef', atomicWriteIORef',
    atomicModifyIORef_, atomicModifyIORef'_
    ) where

import Data.IORef
import Control.Exception


-- | Evaluates the value before calling 'writeIORef'.
writeIORef' :: IORef a -> a -> IO ()
writeIORef' ref x = do
    evaluate x
    writeIORef ref x

-- | Evaluates the value before calling 'atomicWriteIORef'.
atomicWriteIORef' :: IORef a -> a -> IO ()
atomicWriteIORef' ref x = do
    evaluate x
    atomicWriteIORef ref x


-- | Variant of 'atomicModifyIORef' which ignores the return value
atomicModifyIORef_ :: IORef a -> (a -> a) -> IO ()
atomicModifyIORef_ r f = atomicModifyIORef r $ \v -> (f v, ())

-- | Variant of 'atomicModifyIORef'' which ignores the return value
atomicModifyIORef'_ :: IORef a -> (a -> a) -> IO ()
atomicModifyIORef'_ r f = atomicModifyIORef' r $ \v -> (f v, ())