@@ -43,8 +43,14 @@ module Control.Distributed.Process.Internal.Primitives
43
43
, nsendRemote
44
44
-- * Closures
45
45
, unClosure
46
- -- * Auxiliary API
46
+ -- * Exception handling
47
47
, catch
48
+ , mask
49
+ , onException
50
+ , bracket
51
+ , bracket_
52
+ , finally
53
+ -- * Auxiliary API
48
54
, expectTimeout
49
55
, spawnAsync
50
56
, linkNode
@@ -67,8 +73,8 @@ import System.Locale (defaultTimeLocale)
67
73
import Control.Monad.Reader (ask )
68
74
import Control.Monad.IO.Class (MonadIO , liftIO )
69
75
import Control.Applicative ((<$>) )
70
- import Control.Exception (Exception , throw )
71
- import qualified Control.Exception as Ex (catch )
76
+ import Control.Exception (Exception , throw , throwIO , SomeException )
77
+ import qualified Control.Exception as Ex (catch , mask )
72
78
import Control.Concurrent.MVar (modifyMVar )
73
79
import Control.Concurrent.Chan (writeChan )
74
80
import Control.Concurrent.STM
@@ -258,7 +264,7 @@ instance Exception ProcessTerminationException
258
264
259
265
-- | Terminate (throws a ProcessTerminationException)
260
266
terminate :: Process a
261
- terminate = liftIO $ throw ProcessTerminationException
267
+ terminate = liftIO $ throwIO ProcessTerminationException
262
268
263
269
-- | Our own process ID
264
270
getSelfPid :: Process ProcessId
@@ -317,15 +323,51 @@ unmonitor ref = do
317
323
]
318
324
319
325
--------------------------------------------------------------------------------
320
- -- Auxiliary API --
326
+ -- Exception handling --
321
327
--------------------------------------------------------------------------------
322
328
323
- -- | Catch exceptions within a process
329
+ -- | Lift 'Control.Exception.catch'
324
330
catch :: Exception e => Process a -> (e -> Process a ) -> Process a
325
331
catch p h = do
326
332
lproc <- ask
327
333
liftIO $ Ex. catch (runLocalProcess lproc p) (runLocalProcess lproc . h)
328
334
335
+ -- | Lift 'Control.Exception.mask'
336
+ mask :: ((forall a . Process a -> Process a ) -> Process b ) -> Process b
337
+ mask p = do
338
+ lproc <- ask
339
+ liftIO $ Ex. mask $ \ restore ->
340
+ runLocalProcess lproc (p (liftRestore lproc restore))
341
+ where
342
+ liftRestore :: LocalProcess -> (forall a . IO a -> IO a ) -> (forall a . Process a -> Process a )
343
+ liftRestore lproc restoreIO = liftIO . restoreIO . runLocalProcess lproc
344
+
345
+ -- | Lift 'Control.Exception.onException'
346
+ onException :: Process a -> Process b -> Process a
347
+ onException p what = p `catch` \ e -> do _ <- what
348
+ liftIO $ throwIO (e :: SomeException )
349
+
350
+ -- | Lift 'Control.Exception.bracket'
351
+ bracket :: Process a -> (a -> Process b ) -> (a -> Process c ) -> Process c
352
+ bracket before after thing = do
353
+ mask $ \ restore -> do
354
+ a <- before
355
+ r <- restore (thing a) `onException` after a
356
+ _ <- after a
357
+ return r
358
+
359
+ -- | Lift 'Control.Exception.bracket_'
360
+ bracket_ :: Process a -> Process b -> Process c -> Process c
361
+ bracket_ before after thing = bracket before (const after) (const thing)
362
+
363
+ -- | Lift 'Control.Exception.finally'
364
+ finally :: Process a -> Process b -> Process a
365
+ finally a sequel = bracket_ (return () ) sequel a
366
+
367
+ --------------------------------------------------------------------------------
368
+ -- Auxiliary API --
369
+ --------------------------------------------------------------------------------
370
+
329
371
-- | Like 'expect' but with a timeout
330
372
expectTimeout :: forall a . Serializable a => Int -> Process (Maybe a )
331
373
expectTimeout timeout = receiveTimeout timeout [match return ]
@@ -464,7 +506,7 @@ unClosure :: forall a. Typeable a => Closure a -> Process a
464
506
unClosure (Closure (Static label) env) = do
465
507
rtable <- remoteTable . processNode <$> ask
466
508
case resolveClosure rtable label env of
467
- Nothing -> throw . userError $ " Unregistered closure " ++ show label
509
+ Nothing -> error $ " Unregistered closure " ++ show label
468
510
Just dyn -> return $ fromDyn dyn (throw (typeError dyn))
469
511
where
470
512
typeError dyn = userError $ " lookupStatic type error: "
0 commit comments