Skip to content

Commit

Permalink
Lift Control.Exception.catches
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Watson committed Jan 26, 2013
1 parent 205b5ad commit 2419547
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 1 deletion.
4 changes: 4 additions & 0 deletions distributed-process/src/Control/Distributed/Process.hs
Expand Up @@ -101,6 +101,8 @@ module Control.Distributed.Process
, RegisterReply(..) , RegisterReply(..)
-- * Exception handling -- * Exception handling
, catch , catch
, Handler(..)
, catches
, try , try
, mask , mask
, onException , onException
Expand Down Expand Up @@ -238,6 +240,8 @@ import Control.Distributed.Process.Internal.Primitives
, unClosure , unClosure
-- Exception handling -- Exception handling
, catch , catch
, Handler(..)
, catches
, try , try
, mask , mask
, onException , onException
Expand Down
Expand Up @@ -62,6 +62,8 @@ module Control.Distributed.Process.Internal.Primitives
, unStatic , unStatic
-- * Exception handling -- * Exception handling
, catch , catch
, Handler(..)
, catches
, try , try
, mask , mask
, onException , onException
Expand Down Expand Up @@ -96,7 +98,7 @@ import Control.Monad (when)
import Control.Monad.Reader (ask) import Control.Monad.Reader (ask)
import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
import Control.Exception (Exception, throwIO, SomeException) import Control.Exception (Exception(..), throw, throwIO, SomeException)
import qualified Control.Exception as Ex (catch, mask, try) import qualified Control.Exception as Ex (catch, mask, try)
import Control.Distributed.Process.Internal.StrictMVar import Control.Distributed.Process.Internal.StrictMVar
( StrictMVar ( StrictMVar
Expand Down Expand Up @@ -645,6 +647,23 @@ bracket_ before after thing = bracket before (const after) (const thing)
finally :: Process a -> Process b -> Process a finally :: Process a -> Process b -> Process a
finally a sequel = bracket_ (return ()) sequel a finally a sequel = bracket_ (return ()) sequel a


-- | You need this when using 'catches'
data Handler a = forall e . Exception e => Handler (e -> Process a)

instance Functor Handler where
fmap f (Handler h) = Handler (fmap f . h)

-- | Lift 'Control.Exception.catches'
catches :: Process a -> [Handler a] -> Process a
catches proc handlers = proc `catch` catchesHandler handlers

catchesHandler :: [Handler a] -> SomeException -> Process a
catchesHandler handlers e = foldr tryHandler (throw e) handlers
where tryHandler (Handler handler) res
= case fromException e of
Just e' -> handler e'
Nothing -> res

-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Auxiliary API -- -- Auxiliary API --
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Expand Down
16 changes: 16 additions & 0 deletions distributed-process/tests/TestCH.hs
Expand Up @@ -31,6 +31,7 @@ import Control.Distributed.Process.Internal.Types
( NodeId(nodeAddress) ( NodeId(nodeAddress)
, LocalNode(localEndPoint) , LocalNode(localEndPoint)
, ProcessExitException(..) , ProcessExitException(..)
, nullProcessId
) )
import Control.Distributed.Process.Node import Control.Distributed.Process.Node
import Control.Distributed.Process.Serializable (Serializable) import Control.Distributed.Process.Serializable (Serializable)
Expand Down Expand Up @@ -1025,6 +1026,20 @@ testCatchesExit transport = do


takeMVar done takeMVar done


testCatches :: NT.Transport -> Assertion
testCatches transport = do
localNode <- newLocalNode transport initRemoteTable
done <- newEmptyMVar

_ <- forkProcess localNode $ do
node <- getSelfNode
(liftIO $ throwIO (ProcessLinkException (nullProcessId node) DiedNormal))
`catches` [
Handler (\(ProcessLinkException _ _) -> liftIO $ putMVar done ())
]

takeMVar done

testDie :: NT.Transport -> Assertion testDie :: NT.Transport -> Assertion
testDie transport = do testDie transport = do
localNode <- newLocalNode transport initRemoteTable localNode <- newLocalNode transport initRemoteTable
Expand Down Expand Up @@ -1127,6 +1142,7 @@ tests (transport, transportInternals) = [
, testCase "Die" (testDie transport) , testCase "Die" (testDie transport)
, testCase "PrettyExit" (testPrettyExit transport) , testCase "PrettyExit" (testPrettyExit transport)
, testCase "CatchesExit" (testCatchesExit transport) , testCase "CatchesExit" (testCatchesExit transport)
, testCase "Catches" (testCatches transport)
, testCase "ExitLocal" (testExitLocal transport) , testCase "ExitLocal" (testExitLocal transport)
, testCase "ExitRemote" (testExitRemote transport) , testCase "ExitRemote" (testExitRemote transport)
] ]
Expand Down

0 comments on commit 2419547

Please sign in to comment.