summaryrefslogtreecommitdiff
path: root/testsuite/tests/concurrent/should_run/throwto001.hs
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/concurrent/should_run/throwto001.hs')
-rw-r--r--testsuite/tests/concurrent/should_run/throwto001.hs38
1 files changed, 38 insertions, 0 deletions
diff --git a/testsuite/tests/concurrent/should_run/throwto001.hs b/testsuite/tests/concurrent/should_run/throwto001.hs
new file mode 100644
index 0000000000..999d3335d8
--- /dev/null
+++ b/testsuite/tests/concurrent/should_run/throwto001.hs
@@ -0,0 +1,38 @@
+import Control.Concurrent
+import Control.Exception
+import Data.Array
+import System.Random
+import System.Environment
+import Control.Monad
+import GHC.Conc
+
+-- A fiendish throwTo test. A bunch of threads take random MVars from
+-- a shared array; if the MVar has Nothing in it, replace it with Just
+-- of the current thread's ThreadId. If the MVar has another ThreadId
+-- in it, then killThread that thread, and replace it with the current
+-- thread's ThreadId. We keep going until only one thread is left
+-- standing.
+--
+-- On multiple CPUs this should give throwTo a good workout.
+--
+main = do
+ [m, t] <- fmap (fmap read) getArgs
+ ms <- replicateM m $ newMVar Nothing
+ let arr = listArray (1,m) ms
+ dead <- newTVarIO 0
+ ts <- replicateM t $ forkIO (thread m arr `onException`
+ (atomically $ do d <- readTVar dead
+ writeTVar dead $! d+1))
+ atomically $ do
+ d <- readTVar dead
+ when (d < t-1) $ retry
+
+thread m arr = do
+ x <- randomIO
+ id <- myThreadId
+ modifyMVar_ (arr ! ((x `mod` m) + 1)) $ \b ->
+ case b of
+ Nothing -> return (Just id)
+ Just other -> do when (other /= id) $ killThread other
+ return (Just id)
+ thread m arr