packages feed

unagi-chan-0.1.0.2: tests/IndexedMVar.hs

module IndexedMVar (indexedMVarMain) where

import Utilities
import Control.Monad
import Control.Concurrent
import Control.Exception(onException)
import Data.IORef

indexedMVarMain :: IO ()
indexedMVarMain = do
    putStr "Test indexedMVar... "
    replicateM_ 1000 $ 
        indexedMVarTest 128
    putStrLn "OK"

indexedMVarTest :: Int -> IO ()
indexedMVarTest n = do
    let xs = [0..n]
    mvIx <- newIndexedMVar
    start <- newIORef (0::Int)
    _ <- forkIO $ do
           writeIORef start 1
           mapM_ (\x-> putMVarIx mvIx x x `onException` (putStr "In writer: ")) xs
    
    busyWait start
    mapM_ (\x-> (readMVarIx mvIx x `onException` (putStr "In reader: ")) >>= assertEq x) xs
        where assertEq x x' = when (x /= x') $ error $ (show x)++"/="++(show x')

-- we should really abstract this out and use elsewhere
busyWait :: IORef Int -> IO ()
busyWait ref = busy where
    busy = do
         -- N.B. w/ readIORef we loop forever:
        n <- atomicModifyIORef ref (\x-> (x,x)) 
        unless (n == 1) busy