Update the Exception docs
[ghc-base.git] / GHC / Conc.lhs
index 6239278..1d5cc9c 100644 (file)
@@ -37,6 +37,7 @@ module GHC.Conc
         , throwTo       -- :: ThreadId -> Exception -> IO ()
         , par           -- :: a -> b -> b
         , pseq          -- :: a -> b -> b
+        , runSparks
         , yield         -- :: IO ()
         , labelThread   -- :: ThreadId -> String -> IO ()
 
@@ -72,6 +73,7 @@ module GHC.Conc
         , newTVar       -- :: a -> STM (TVar a)
         , newTVarIO     -- :: a -> STM (TVar a)
         , readTVar      -- :: TVar a -> STM a
+        , readTVarIO    -- :: TVar a -> IO a
         , writeTVar     -- :: a -> TVar a -> STM ()
         , unsafeIOToSTM -- :: IO a -> STM a
 
@@ -203,6 +205,11 @@ library that uses thread-local storage, use 'Control.Concurrent.forkOS' instead.
 
 GHC note: the new thread inherits the /blocked/ state of the parent 
 (see 'Control.Exception.block').
+
+The newly created thread has an exception handler that discards the
+exceptions 'BlockedOnDeadMVar', 'BlockedIndefinitely', and
+'ThreadKilled', and passes all other exceptions to the uncaught
+exception handler (see 'setUncaughtExceptionHandler').
 -}
 forkIO :: IO () -> IO ThreadId
 forkIO action = IO $ \ s -> 
@@ -238,8 +245,11 @@ numCapabilities = unsafePerformIO $  do
                     n <- peek n_capabilities
                     return (fromIntegral n)
 
+#if defined(mingw32_HOST_OS) && defined(__PIC__)
+foreign import ccall "_imp__n_capabilities" n_capabilities :: Ptr CInt
+#else
 foreign import ccall "&n_capabilities" n_capabilities :: Ptr CInt
-
+#endif
 childHandler :: SomeException -> IO ()
 childHandler err = catchException (real_handler err) childHandler
 
@@ -266,6 +276,7 @@ terms of 'throwTo':
 
 > killThread tid = throwTo tid ThreadKilled
 
+Killthread is a no-op if the target thread has already completed.
 -}
 killThread :: ThreadId -> IO ()
 killThread tid = throwTo tid ThreadKilled
@@ -290,12 +301,12 @@ the paper \"Asynchronous exceptions in Haskell\"
 (<http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm>).
 In the paper, 'throwTo' is non-blocking; but the library implementation adopts
 a more synchronous design in which 'throwTo' does not return until the exception
-is received by the target thread.  The trade-off is discussed in Section 8 of the paper.
-Like any blocking operation, 'throwTo' is therefore interruptible (see Section 4.3 of
+is received by the target thread.  The trade-off is discussed in Section 9 of the paper.
+Like any blocking operation, 'throwTo' is therefore interruptible (see Section 5.3 of
 the paper).
 
 There is currently no guarantee that the exception delivered by 'throwTo' will be
-delivered at the first possible opportunity.  In particular, if a thread may 
+delivered at the first possible opportunity.  In particular, a thread may 
 unblock and then re-block exceptions (using 'unblock' and 'block') without receiving
 a pending 'throwTo'.  This is arguably undesirable behaviour.
 
@@ -353,6 +364,13 @@ pseq  x y = x `seq` lazy y
 par :: a -> b -> b
 par  x y = case (par# x) of { _ -> lazy y }
 
+-- | Internal function used by the RTS to run sparks.
+runSparks :: IO ()
+runSparks = IO loop
+  where loop s = case getSpark# s of
+                   (# s', n, p #) ->
+                      if n ==# 0# then (# s', () #)
+                                  else p `seq` loop s'
 
 data BlockReason
   = BlockedOnMVar
@@ -549,6 +567,16 @@ newTVarIO val = IO $ \s1# ->
     case newTVar# val s1# of
          (# s2#, tvar# #) -> (# s2#, TVar tvar# #)
 
+-- |Return the current value stored in a TVar.
+-- This is equivalent to
+--
+-- >  readTVarIO = atomically . readTVar
+--
+-- but works much faster, because it doesn't perform a complete
+-- transaction, it just reads the current value of the 'TVar'.
+readTVarIO :: TVar a -> IO a
+readTVarIO (TVar tvar#) = IO $ \s# -> readTVarIO# tvar# s#
+
 -- |Return the current value stored in a TVar
 readTVar :: TVar a -> STM a
 readTVar (TVar tvar#) = STM $ \s# -> readTVar# tvar# s#