spawn-0.2: Control/Concurrent/Spawn.hs
module Control.Concurrent.Spawn
( -- * Spawn
spawn
-- * Spawn with @'try'@
, Result
, spawnTry
-- * Limiting concurrency
, pool ) where
import Control.Concurrent
import Control.Exception
-- | Two ways a computation of type @'IO' a@ can end.
type Result a = Either SomeException a
-- | Spawn a concurrent computation. Produces an action which
-- demands a @'Result'@.
spawnTry :: IO a -> IO (IO (Result a))
spawnTry m = do
v <- newEmptyMVar
-- block async exns, then unblock inside 'try' unless parent was blocked
-- avoids dropping an exception
b <- blocked
_ <- block $ forkIO (try (if b then m else unblock m) >>= putMVar v)
return (readMVar v)
-- | Spawn a concurrent computation. Produces an action which
-- demands the result. Any exception from the original computation
-- is re-thrown when and where the result is demanded.
spawn :: IO a -> IO (IO a)
spawn m = do
r <- spawnTry m
return (r >>= either throwIO return)
-- | Given /n/, produces a function to wrap @'IO'@ actions.
-- No more than /n/ wrapped actions will be in progress at
-- one time.
pool :: Int -> IO (IO a -> IO a)
pool n = do
s <- newQSem n
return $ bracket_ (waitQSem s) (signalQSem s)