X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Control%2FConcurrent.hs;h=79b8352f5002174e12372de73dcf2f8c23fc72c4;hb=0c074a8eef70fd5c9ff19db84eb3564b9e3a89d3;hp=6122a102b7b09cee55d9b5cfbfd11d0d9b26f6bc;hpb=4c29f6f110d23b890567b8696a964bb212eba52e;p=ghc-base.git diff --git a/Control/Concurrent.hs b/Control/Concurrent.hs index 6122a10..79b8352 100644 --- a/Control/Concurrent.hs +++ b/Control/Concurrent.hs @@ -406,13 +406,10 @@ runInBoundThread action else do ref <- newIORef undefined let action_plus = Exception.try action >>= writeIORef ref - resultOrException <- - bracket (newStablePtr action_plus) - freeStablePtr - (\cEntry -> forkOS_entry_reimported cEntry >> readIORef ref) - case resultOrException of - Left exception -> Exception.throw (exception :: SomeException) - Right result -> return result + bracket (newStablePtr action_plus) + freeStablePtr + (\cEntry -> forkOS_entry_reimported cEntry >> readIORef ref) >>= + unsafeResult | otherwise = failNonThreaded {- | @@ -425,23 +422,27 @@ performance loss due to the use of bound threads. A program that doesn't need it's main thread to be bound and makes /heavy/ use of concurrency (e.g. a web server), might want to wrap it's @main@ action in @runInUnboundThread@. + +Note that exceptions which are thrown to the current thread are thrown in turn +to the thread that is executing the given computation. This ensures there's +always a way of killing the forked thread. -} runInUnboundThread :: IO a -> IO a runInUnboundThread action = do - bound <- isCurrentThreadBound - if bound - then do - mv <- newEmptyMVar - b <- blocked - _ <- mask $ \restore -> forkIO $ - Exception.try (if b then action else restore action) >>= - putMVar mv - takeMVar mv >>= \ei -> case ei of - Left exception -> Exception.throw (exception :: SomeException) - Right result -> return result - else action - + bound <- isCurrentThreadBound + if bound + then do + mv <- newEmptyMVar + mask $ \restore -> do + tid <- forkIO $ Exception.try (restore action) >>= putMVar mv + let wait = takeMVar mv `Exception.catch` \(e :: SomeException) -> + Exception.throwTo tid e >> wait + wait >>= unsafeResult + else action + +unsafeResult :: Either SomeException a -> IO a +unsafeResult = either Exception.throwIO return #endif /* __GLASGOW_HASKELL__ */ #ifdef __GLASGOW_HASKELL__