projects
/
ghc-base.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
add ga_inl, ga_inr
[ghc-base.git]
/
Control
/
Concurrent.hs
diff --git
a/Control/Concurrent.hs
b/Control/Concurrent.hs
index
bd05cdc
..
62a30b4
100644
(file)
--- a/
Control/Concurrent.hs
+++ b/
Control/Concurrent.hs
@@
-1,4
+1,11
@@
+{-# LANGUAGE CPP
+ , ForeignFunctionInterface
+ , MagicHash
+ , UnboxedTuples
+ , ScopedTypeVariables
+ #-}
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
-----------------------------------------------------------------------------
-- |
-- Module : Control.Concurrent
-----------------------------------------------------------------------------
-- |
-- Module : Control.Concurrent
@@
-28,11
+35,17
@@
module Control.Concurrent (
forkIO,
#ifdef __GLASGOW_HASKELL__
forkIO,
#ifdef __GLASGOW_HASKELL__
- forkIOUnmasked,
+ forkIOWithUnmask,
killThread,
throwTo,
#endif
killThread,
throwTo,
#endif
+ -- ** Threads with affinity
+ forkOn,
+ forkOnWithUnmask,
+ getNumCapabilities,
+ threadCapability,
+
-- * Scheduling
-- $conc_scheduling
-- * Scheduling
-- $conc_scheduling
@@
-71,7
+84,7
@@
module Control.Concurrent (
forkOS,
isCurrentThreadBound,
runInBoundThread,
forkOS,
isCurrentThreadBound,
runInBoundThread,
- runInUnboundThread
+ runInUnboundThread,
#endif
-- * GHC's implementation of concurrency
#endif
-- * GHC's implementation of concurrency
@@
-90,6
+103,10
@@
module Control.Concurrent (
-- ** Pre-emption
-- $preemption
-- ** Pre-emption
-- $preemption
+
+ -- * Deprecated functions
+ forkIOUnmasked
+
) where
import Prelude
) where
import Prelude
@@
-98,8
+115,7
@@
import Control.Exception.Base as Exception
#ifdef __GLASGOW_HASKELL__
import GHC.Exception
#ifdef __GLASGOW_HASKELL__
import GHC.Exception
-import GHC.Conc ( ThreadId(..), myThreadId, killThread, yield,
- threadDelay, forkIO, forkIOUnmasked, childHandler )
+import GHC.Conc hiding (threadWaitRead, threadWaitWrite)
import qualified GHC.Conc
import GHC.IO ( IO(..), unsafeInterleaveIO, unsafeUnmask )
import GHC.IORef ( newIORef, readIORef, writeIORef )
import qualified GHC.Conc
import GHC.IO ( IO(..), unsafeInterleaveIO, unsafeUnmask )
import GHC.IORef ( newIORef, readIORef, writeIORef )
@@
-422,18
+438,24
@@
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@.
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
-}
runInUnboundThread :: IO a -> IO a
runInUnboundThread action = do
- bound <- isCurrentThreadBound
- if bound
- then do
- mv <- newEmptyMVar
- _ <- mask $ \restore -> forkIO $
- Exception.try (restore action) >>= putMVar mv
- takeMVar mv >>= unsafeResult
- 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
unsafeResult :: Either SomeException a -> IO a
unsafeResult = either Exception.throwIO return
@@
-445,6
+467,11
@@
unsafeResult = either Exception.throwIO return
-- | Block the current thread until data is available to read on the
-- given file descriptor (GHC only).
-- | Block the current thread until data is available to read on the
-- given file descriptor (GHC only).
+--
+-- This will throw an 'IOError' if the file descriptor was closed
+-- while this thread was blocked. To safely close a file descriptor
+-- that has been used with 'threadWaitRead', use
+-- 'GHC.Conc.closeFdWith'.
threadWaitRead :: Fd -> IO ()
threadWaitRead fd
#ifdef mingw32_HOST_OS
threadWaitRead :: Fd -> IO ()
threadWaitRead fd
#ifdef mingw32_HOST_OS
@@
-465,6
+492,11
@@
threadWaitRead fd
-- | Block the current thread until data can be written to the
-- given file descriptor (GHC only).
-- | Block the current thread until data can be written to the
-- given file descriptor (GHC only).
+--
+-- This will throw an 'IOError' if the file descriptor was closed
+-- while this thread was blocked. To safely close a file descriptor
+-- that has been used with 'threadWaitWrite', use
+-- 'GHC.Conc.closeFdWith'.
threadWaitWrite :: Fd -> IO ()
threadWaitWrite fd
#ifdef mingw32_HOST_OS
threadWaitWrite :: Fd -> IO ()
threadWaitWrite fd
#ifdef mingw32_HOST_OS
@@
-489,7
+521,7
@@
withThread io = do
waitFd :: Fd -> CInt -> IO ()
waitFd fd write = do
throwErrnoIfMinus1_ "fdReady" $
waitFd :: Fd -> CInt -> IO ()
waitFd fd write = do
throwErrnoIfMinus1_ "fdReady" $
- fdReady (fromIntegral fd) write (fromIntegral iNFINITE) 0
+ fdReady (fromIntegral fd) write iNFINITE 0
iNFINITE :: CInt
iNFINITE = 0xFFFFFFFF -- urgh
iNFINITE :: CInt
iNFINITE = 0xFFFFFFFF -- urgh