diff options
author | Simon Marlow <marlowsd@gmail.com> | 2010-07-08 15:27:35 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2010-07-08 15:27:35 +0000 |
commit | 73157075b708095b14a8551ca2f296a8b4f2550b (patch) | |
tree | b38aa88732e04ebf6e859423ed5f3a592a3313f9 /libraries/base/Control/Exception.hs | |
parent | 3ae2fa064d02837651c305f2e8815e5e1e614029 (diff) | |
download | haskell-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.hs | 27 |
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 |