summaryrefslogtreecommitdiff
path: root/libraries/base/Control/Exception.hs
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2010-07-08 15:27:35 +0000
committerSimon Marlow <marlowsd@gmail.com>2010-07-08 15:27:35 +0000
commit73157075b708095b14a8551ca2f296a8b4f2550b (patch)
treeb38aa88732e04ebf6e859423ed5f3a592a3313f9 /libraries/base/Control/Exception.hs
parent3ae2fa064d02837651c305f2e8815e5e1e614029 (diff)
downloadhaskell-73157075b708095b14a8551ca2f296a8b4f2550b.tar.gz
New asynchronous exception control API (base parts)
As discussed on the libraries/haskell-cafe mailing lists http://www.haskell.org/pipermail/libraries/2010-April/013420.html This is a replacement for block/unblock in the asychronous exceptions API to fix a problem whereby a function could unblock asynchronous exceptions even if called within a blocked context. The new terminology is "mask" rather than "block" (to avoid confusion due to overloaded meanings of the latter). The following is the new API; the old API is deprecated but still available for the time being. Control.Exception ----------------- mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b mask_ :: IO a -> IO a uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b uninterruptibleMask_ :: IO a -> IO getMaskingState :: IO MaskingState data MaskingState = Unmasked | MaskedInterruptible | MaskedUninterruptible Control.Concurrent ------------------ forkIOUnmasked :: IO () -> IO ThreadId
Diffstat (limited to 'libraries/base/Control/Exception.hs')
-rw-r--r--libraries/base/Control/Exception.hs27
1 files changed, 17 insertions, 10 deletions
diff --git a/libraries/base/Control/Exception.hs b/libraries/base/Control/Exception.hs
index 47bb057568..bbcc490032 100644
--- a/libraries/base/Control/Exception.hs
+++ b/libraries/base/Control/Exception.hs
@@ -104,9 +104,18 @@ module Control.Exception (
-- ** Asynchronous exception control
- -- |The following two functions allow a thread to control delivery of
+ -- |The following functions allow a thread to control delivery of
-- asynchronous exceptions during a critical region.
+ mask,
+ mask_,
+ uninterruptibleMask,
+ uninterruptibleMask_,
+ MaskingState(..),
+ getMaskingState,
+
+ -- ** (deprecated) Asynchronous exception control
+
block,
unblock,
blocked,
@@ -138,7 +147,6 @@ import Control.Exception.Base
#ifdef __GLASGOW_HASKELL__
import GHC.Base
--- import GHC.IO hiding ( onException, finally )
import Data.Maybe
#else
import Prelude hiding (catch)
@@ -243,7 +251,7 @@ easy to introduce race conditions by the over zealous use of
-}
{- $block_handler
-There\'s an implied 'block' around every exception handler in a call
+There\'s an implied 'mask' around every exception handler in a call
to one of the 'catch' family of functions. This is because that is
what you want most of the time - it eliminates a common race condition
in starting an exception handler, because there may be no exception
@@ -253,10 +261,9 @@ handler, though, we have time to install a new exception handler
before being interrupted. If this weren\'t the default, one would have
to write something like
-> block (
-> catch (unblock (...))
-> (\e -> handler)
-> )
+> block $ \restore ->
+> catch (restore (...))
+> (\e -> handler)
If you need to unblock asynchronous exceptions again in the exception
handler, just use 'unblock' as normal.
@@ -268,6 +275,7 @@ recovering from an asynchronous exception.
{- $interruptible
+ #interruptible#
Some operations are /interruptible/, which means that they can receive
asynchronous exceptions even in the scope of a 'block'. Any function
which may itself block is defined as interruptible; this includes
@@ -277,11 +285,10 @@ and most operations which perform
some I\/O with the outside world. The reason for having
interruptible operations is so that we can write things like
-> block (
+> mask $ \restore -> do
> a <- takeMVar m
-> catch (unblock (...))
+> catch (restore (...))
> (\e -> ...)
-> )
if the 'Control.Concurrent.MVar.takeMVar' was not interruptible,
then this particular