import System.GlobalLock

import Data.IORef
import Control.Monad
import Control.Concurrent
import Control.Concurrent.Spawn  -- package 'spawn'
import System.Exit
import System.Random

thread :: IORef Int -> IO ()
thread ref = replicateM_ 40 . lock $ do
    v <- readIORef ref
    when (v /= 0) $ do
        putStrLn "ERROR: mutual exclusion violation"
        exitFailure

    atomicModifyIORef ref (\n -> (n+1,()))
    delay <- randomRIO (0,4000)
    threadDelay delay
    atomicModifyIORef ref (\n -> (n-1,()))

main :: IO ()
main = do
    ref <- newIORef 0
    parMapIO_ (const $ thread ref) [0..200]
