Brad Clow: > If you would like to wait on multiple threads, you can use STM like so: > > import Control.Concurrent > import Control.Concurrent.STM > import Control.Exception > > main = do > tc <- atomically $ newTVar 2 > run tc (print (last [1..100000000])) > run tc (print (last [1..110000000])) > print "Waiting...." > atomically $ readTVar tc >>= \x -> if x == 0 then return () else retry > print "OK." > where > run tc f = forkIO (f `finally` atomReplace (\x -> x - 1) tc) > > atomReplace fn x = atomically $ readTVar x >>= writeTVar x . fn
Nice! Although, to wait for all of a set of threads, you really only need to wait for each in turn, so you could do this with plain MVars. The real power of STM becomes apparent when you need to wait for any of a set of results, for example: > import Control.Arrow > import Control.Concurrent > import Control.Concurrent.STM > import Control.Concurrent.STM.TVar > > newtype Wait a = Wait (TVar (Maybe a)) > > fork :: IO a -> IO (Wait a) > fork m = do > w <- atomically (newTVar Nothing) > forkIO (m >>= atomically . writeTVar w . Just) > return (Wait w) > > wait :: Wait a -> IO a > wait (Wait w) = atomically $ do > r <- readTVar w > case r of > Just a -> return a > Nothing -> retry > > wait_all :: [Wait a] -> IO [a] > wait_all [] = return [] > wait_all (w:ws) = do > r <- wait w > t <- wait_all ws > return (r:t) > > wait_first :: [Wait a] -> IO (a, [Wait a]) > wait_first [] = error "wait_first: nothing to wait for" > wait_first ws = atomically (do_wait ws) where > do_wait [] = retry > do_wait (Wait w : ws) = do > r <- readTVar w > case r of > Nothing -> fmap (second (Wait w:)) (do_wait ws) > Just s -> return (s,ws) > > main = do > w1 <- fork (test 50000000) > w2 <- fork (test 10000000) > w3 <- fork (test 100000000) > (r,ws) <- wait_first [w1,w2,w3] > putStrLn ("First result: " ++ show r) > rs <- wait_all ws > putStrLn ("Remaining results: " ++ show rs) > > test :: Integer -> IO Integer > test i = do > let r = last [1..i] > putStrLn ("Result " ++ show r) > return r You might recognise the Wait type as being identical to TMVar, although I use a slightly different set of operations. Throw Control.Concurrent.STM.TChan into the mix, and you have some very rich possibilities indeed. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe