{-| Module : Control.Concurrent.Concurrential.Safely Description : Handle all exceptions in Concurrential computation. Copyright : (c) Alexander Vieth, 2015 Licence : BSD3 Maintainer : aovieth@gmail.com Stability : experimental Portability : non-portable (GHC only) -} {-# LANGUAGE ScopedTypeVariables #-} module Control.Concurrent.Concurrential.Safely ( safely , runSafely ) where import Control.Applicative import Control.Monad import Control.Exception import Control.Concurrent.Except import Control.Concurrent.Concurrential injector :: Injector (ExceptT SomeException IO) (Either SomeException) injector term = runExceptT term >>= return retractor :: Retractor (Either SomeException) retractor term = case term of Left e -> return $ Left e Right v -> v -- | Make an arbitrary IO suitable for use with @sequentially@ or @concurrently@ -- so as to produce a term that can be run by @runSafely@: -- -- let a = concurrently . safely $ dangerousComputation1 -- b = concurrently . safely $ dangerousComputation2 -- in runSafely $ a *> b -- safely :: IO a -> ExceptT SomeException IO a safely io = ExceptT ((Right <$> io) `catch` (\(e :: SomeException) -> return $ Left e)) -- | Run a term such that computation is halted as soon as an exception is -- encountered, but any pending threads are waited on. The first exception -- to be thown (in term-order, not necessarily temporal order) is given as -- Left, and a Right is given if no exception is encountered. runSafely :: Concurrential (ExceptT SomeException IO) a -> IO (Either SomeException a) runSafely = runConcurrential retractor injector