import Data.IORef (IORef, newIORef, atomicModifyIORef, readIORef)
import System.IO.Unsafe (unsafePerformIO)
import Control.Concurrent (threadDelay)
import Control.Parallel (par)
import Control.DeepSeq (force, NFData)
delayed_inc :: Int -> Int
delayed_inc x = (unsafePerformIO $
do
putStrLn "Incrementing variable (waiting 2 seconds)..."
threadDelay 2000000
putStrLn "Done incrementing variable."
) `seq` (x + 1)
f :: Int -> (Int, ())
f x = (delayed_inc x, ())
atomicModifyIORefPar :: (NFData a) => IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORefPar ioref f =
let g olddata = (let (newdata, result) = f olddata in (newdata, (result, newdata)))
in do
(result, newdata) <- atomicModifyIORef ioref g
force newdata `par` return result
main :: IO ()
main =
do
ioref <- newIORef 20
putStrLn "Modifying IORef..."
atomicModifyIORefPar ioref f
putStrLn "Waiting 5 seconds..."
threadDelay 5000000
putStrLn "Reading variable..."
newiorefval <- readIORef ioref
putStrLn "Showing variable..."
putStrLn $ show newiorefval
threadDelay 5000000