#endif
-- $merge
+#ifdef __GLASGOW_HASKELL__
-- * Bound Threads
-- $boundthreads
-#ifdef __GLASGOW_HASKELL__
rtsSupportsBoundThreads,
forkOS,
isCurrentThreadBound,
- runInBoundThread
+ runInBoundThread,
+ runInUnboundThread
#endif
-- * GHC's implementation of concurrency
import Control.Exception as Exception
#ifdef __GLASGOW_HASKELL__
-import GHC.Conc
+import GHC.Conc ( ThreadId(..), myThreadId, killThread, yield,
+ threadDelay, threadWaitRead, threadWaitWrite )
import GHC.TopHandler ( reportStackOverflow, reportError )
import GHC.IOBase ( IO(..) )
import GHC.IOBase ( unsafeInterleaveIO )
Scheduling may be either pre-emptive or co-operative,
depending on the implementation of Concurrent Haskell (see below
- for imformation related to specific compilers). In a co-operative
+ for information related to specific compilers). In a co-operative
system, context switches only occur when you use one of the
primitives defined in this module. This means that programs such
as:
-- report all others:
AsyncException StackOverflow -> reportStackOverflow False
- ErrorCall s -> reportError False s
- other -> reportError False (showsPrec 0 other "\n")
+ other -> reportError False other
#endif /* __GLASGOW_HASKELL__ */
mapIO f xs = sequence (map f xs)
#endif /* __HUGS__ */
+#ifdef __GLASGOW_HASKELL__
-- ---------------------------------------------------------------------------
-- Bound Threads
{- $boundthreads
Support for multiple operating system threads and bound threads as described
-below is currently only available in the GHC runtime system when the runtime system
-has been compiled using a special option.
-
-When recompiling GHC, use ./configure --enable-threaded-rts to enable this.
-To find your GHC has already been compiled that way, use
-'rtsSupportsBoundThreads' from GHCi.
+below is currently only available in the GHC runtime system if you use the
+/-threaded/ option when linking.
Other Haskell systems do not currently support multiple operating system threads.
from @main@ or from a @foreign export@.
-}
-#ifdef __GLASGOW_HASKELL__
-
-- | 'True' if bound threads are supported.
-- If @rtsSupportsBoundThreads@ is 'False', 'isCurrentThreadBound'
-- will always return 'False' and both 'forkOS' and 'runInBoundThread' will
foreign import ccall forkOS_createThread
:: StablePtr (IO ()) -> IO CInt
+failNonThreaded = fail $ "RTS doesn't support multiple OS threads "
+ ++"(use ghc -threaded when linking)"
+
forkOS action
| rtsSupportsBoundThreads = do
mv <- newEmptyMVar
tid <- takeMVar mv
freeStablePtr entry
return tid
- | otherwise = fail "RTS not built to support multiple OS threads."
+ | otherwise = failNonThreaded
-- | Returns 'True' if the calling thread is /bound/, that is, if it is
-- safe to use foreign libraries that rely on thread-local state from the
case resultOrException of
Left exception -> Exception.throw exception
Right result -> return result
- | otherwise = fail "RTS not built to support multiple OS threads."
+ | otherwise = failNonThreaded
{- |
Run the 'IO' computation passed as the first argument. If the calling thread
runInUnboundThread :: IO a -> IO a
runInUnboundThread action = do
- bound <- isCurrentThreadBound
- if bound
- then do
- mv <- newEmptyMVar
- forkIO (Exception.try action >>= putMVar mv)
- takeMVar mv >>= \either -> case either of
- Left exception -> Exception.throw exception
- Right result -> return result
- else action
+ bound <- isCurrentThreadBound
+ if bound
+ then do
+ mv <- newEmptyMVar
+ forkIO (Exception.try action >>= putMVar mv)
+ takeMVar mv >>= \either -> case either of
+ Left exception -> Exception.throw exception
+ Right result -> return result
+ else action
-#endif
+#endif /* __GLASGOW_HASKELL__ */
-- ---------------------------------------------------------------------------
-- More docs
a thread may be pre-empted whenever it allocates some memory,
which unfortunately means that tight loops which do no
allocation tend to lock out other threads (this only seems to
- happen with pathalogical benchmark-style code, however).
+ happen with pathological benchmark-style code, however).
The rescheduling timer runs on a 20ms granularity by
default, but this may be altered using the