summaryrefslogtreecommitdiff
path: root/libraries/base/tests/qsemn001.hs
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2012-12-10 13:39:11 +0000
committerSimon Marlow <marlowsd@gmail.com>2012-12-10 14:07:04 +0000
commit2f32d1d2a0c3c066e26dc9966ef47cb27b3944a4 (patch)
treef21e2294518403b2c5c83c2c6f1a945ac1a88883 /libraries/base/tests/qsemn001.hs
parent756a970eacbb6a19230ee3ba57e24999e4157b09 (diff)
downloadhaskell-2f32d1d2a0c3c066e26dc9966ef47cb27b3944a4.tar.gz
Add back new working QSem and QSemN implementations (#7417)
We decided not to break existing users without providing an easy migration path. For the time being I've made these implementations, which fix the bugs in the old versions and perform reasonably well. In due course we should move the concurrency functionality, including these modules, out of base and into a separate package.
Diffstat (limited to 'libraries/base/tests/qsemn001.hs')
-rw-r--r--libraries/base/tests/qsemn001.hs110
1 files changed, 110 insertions, 0 deletions
diff --git a/libraries/base/tests/qsemn001.hs b/libraries/base/tests/qsemn001.hs
new file mode 100644
index 0000000000..db44bbbb49
--- /dev/null
+++ b/libraries/base/tests/qsemn001.hs
@@ -0,0 +1,110 @@
+{-# LANGUAGE CPP #-}
+import Control.Concurrent
+import Control.Exception
+import Control.Monad
+import Control.Concurrent.STM
+
+new = newQSemN
+wait = waitQSemN
+signal = signalQSemN
+
+--------
+-- dummy test-framework
+
+type Assertion = IO ()
+
+x @?= y = when (x /= y) $ error (show x ++ " /= " ++ show y)
+
+testCase :: String -> IO () -> IO ()
+testCase n io = putStrLn ("test " ++ n) >> io
+
+defaultMain = sequence
+------
+
+main = defaultMain tests
+
+tests = [
+ testCase "semn" semn,
+ testCase "semn2" semn2,
+ testCase "semn3" semn3,
+ testCase "semn_kill" semn_kill,
+ testCase "semn_bracket" sem_bracket
+ ]
+
+semn :: Assertion
+semn = do
+ c <- newTChanIO
+ q <- new 0
+ t1 <- forkIO $ do wait q 1; atomically $ writeTChan c 'a'
+ threadDelay 10000
+ t2 <- forkIO $ do wait q 2; atomically $ writeTChan c 'b'
+ threadDelay 10000
+ t3 <- forkIO $ do wait q 3; atomically $ writeTChan c 'c'
+ threadDelay 10000
+ signal q 1
+ a <- atomically $ readTChan c
+ signal q 2
+ b <- atomically $ readTChan c
+ signal q 3
+ c <- atomically $ readTChan c
+ [a,b,c] @?= "abc"
+
+semn2 :: Assertion
+semn2 = do
+ c <- newTChanIO
+ q <- new 0
+ t1 <- forkIO $ do wait q 1; threadDelay 10000; atomically $ writeTChan c 'a'
+ threadDelay 10000
+ t2 <- forkIO $ do wait q 2; threadDelay 20000; atomically $ writeTChan c 'b'
+ threadDelay 10000
+ t3 <- forkIO $ do wait q 3; threadDelay 30000; atomically $ writeTChan c 'c'
+ threadDelay 10000
+ signal q 6
+ a <- atomically $ readTChan c
+ b <- atomically $ readTChan c
+ c <- atomically $ readTChan c
+ [a,b,c] @?= "abc"
+
+semn3 :: Assertion
+semn3 = do
+ c <- newTChanIO
+ q <- new 0
+ t1 <- forkIO $ do wait q 1; threadDelay 10000; atomically $ writeTChan c 'a'
+ threadDelay 10000
+ t2 <- forkIO $ do wait q 2; threadDelay 20000; atomically $ writeTChan c 'b'
+ threadDelay 10000
+ t3 <- forkIO $ do wait q 3; threadDelay 30000; atomically $ writeTChan c 'c'
+ threadDelay 10000
+ signal q 3
+ a <- atomically $ readTChan c
+ b <- atomically $ readTChan c
+ threadDelay 10000
+ [a,b] @?= "ab"
+ d <- atomically $ isEmptyTChan c
+ d @?= True
+ signal q 1
+ threadDelay 10000
+ d <- atomically $ isEmptyTChan c
+ d @?= True
+ signal q 2
+ x <- atomically $ readTChan c
+ x @?= 'c'
+
+semn_kill :: Assertion
+semn_kill = do
+ q <- new 0
+ t <- forkIO $ do wait q 1
+ threadDelay 10000
+ killThread t
+ m <- newEmptyMVar
+ t <- forkIO $ do wait q 1; putMVar m ()
+ signal q 1
+ takeMVar m
+
+sem_bracket :: Assertion
+sem_bracket = do
+ q <- new 1
+ ts <- forM [1..100000] $ \n -> do
+ forkIO $ do bracket_ (wait q 1) (signal q 1) (return ())
+ mapM_ killThread ts
+ wait q 1