{-# LANGUAGE CPP #-} import GetURL import Control.Concurrent #if __GLASGOW_HASKELL__ < 706 import ConcurrentUtils (forkFinally) #endif import Control.Exception import qualified Data.ByteString as B import Control.Concurrent.STM ----------------------------------------------------------------------------- -- Our Async API: -- <> -- < IO (Async a) async action = do var <- newEmptyTMVarIO t <- forkFinally action (atomically . putTMVar var) return (Async t var) -- >> --- < IO (Either SomeException a) waitCatch = atomically . waitCatchSTM -- >> -- < STM (Either SomeException a) waitCatchSTM (Async _ var) = readTMVar var -- >> -- < STM a waitSTM a = do r <- waitCatchSTM a case r of Left e -> throwSTM e Right a -> return a -- >> -- < IO a wait = atomically . waitSTM -- >> -- < IO () cancel (Async t _) = throwTo t ThreadKilled -- >> -- < Async b -> IO (Either a b) waitEither a b = atomically $ fmap Left (waitSTM a) `orElse` fmap Right (waitSTM b) -- >> -- < IO a waitAny asyncs = atomically $ foldr orElse retry $ map waitSTM asyncs -- >> -- < (Async a -> IO b) -> IO b withAsync io operation = bracket (async io) cancel operation -- >> ----------------------------------------------------------------------------- -- <
withAsync (getURL "http://www.wikipedia.org/wiki/Spade") $ \a2 -> do r1 <- wait a1 r2 <- wait a2 print (B.length r1, B.length r2) -- >>