resourcet 0.4.9 → 0.4.10
raw patch · 3 files changed
+90/−3 lines, 3 files
Files
- Control/Monad/Trans/Resource.hs +18/−0
- Control/Monad/Trans/Resource/Internal.hs +71/−2
- resourcet.cabal +1/−1
Control/Monad/Trans/Resource.hs view
@@ -58,6 +58,11 @@ , withInternalState , createInternalState , closeInternalState+ -- * Resource+ , Resource+ , mkResource+ , with+ , allocateResource ) where import qualified Data.IntMap as IntMap@@ -135,6 +140,13 @@ -> m (ReleaseKey, a) allocate a = liftResourceT . allocateRIO a +-- | Allocate a resource and register an action with the @MonadResource@ to+-- free the resource.+--+-- Since 0.4.10+allocateResource :: MonadResource m => Resource a -> m (ReleaseKey, a)+allocateResource = liftResourceT . allocateResourceRIO+ -- | Perform asynchronous exception masking. -- -- This is more general then @Control.Exception.mask@, yet more efficient@@ -148,6 +160,12 @@ allocateRIO acquire rel = ResourceT $ \istate -> liftIO $ E.mask $ \restore -> do a <- restore acquire key <- register' istate $ rel a+ return (key, a)++allocateResourceRIO :: Resource a -> ResourceT IO (ReleaseKey, a)+allocateResourceRIO (Resource f) = ResourceT $ \istate -> liftIO $ E.mask $ \restore -> do+ Allocated a free <- f restore+ key <- register' istate free return (key, a) registerRIO :: IO () -> ResourceT IO ReleaseKey
Control/Monad/Trans/Resource/Internal.hs view
@@ -1,9 +1,11 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE RankNTypes #-} module Control.Monad.Trans.Resource.Internal( ExceptionT(..)@@ -18,13 +20,17 @@ , stateAlloc , stateCleanup , transResourceT+ , Resource (..)+ , Allocated (..)+ , with+ , mkResource ) where import Control.Exception (throw,Exception,SomeException) import Control.Applicative (Applicative (..)) import Control.Monad.Trans.Control ( MonadTransControl (..), MonadBaseControl (..)- , ComposeSt, defaultLiftBaseWith, defaultRestoreM)+ , ComposeSt, defaultLiftBaseWith, defaultRestoreM, control) import Control.Monad.Base (MonadBase, liftBase) import Control.Monad.Trans.Cont ( ContT ) import Control.Monad.Cont.Class ( MonadCont (..) )@@ -48,7 +54,7 @@ import qualified Control.Monad.Trans.Writer.Strict as Strict ( WriterT ) import Control.Monad.IO.Class (MonadIO (..))-import Control.Monad (liftM)+import Control.Monad (liftM, ap) import qualified Control.Exception as E import Control.Monad.ST (ST) import Data.IntMap (IntMap)@@ -418,3 +424,66 @@ return $! case a of Left l -> (Left l, id) Right (r, f) -> (Right r, f)++data Allocated a = Allocated !a !(IO ())++-- | A method for allocating a scarce resource, providing the means of freeing+-- it when no longer needed. This data type provides+-- @Functor@/@Applicative@/@Monad@ instances for composing different resources+-- together. You can allocate these resources using either the @bracket@+-- pattern (via @with@) or using @ResourceT@ (via @allocateResource@).+--+-- This concept was originally introduced by Gabriel Gonzalez and described at:+-- <http://www.haskellforall.com/2013/06/the-resource-applicative.html>. The+-- implementation in this package is slightly different, due to taking a+-- different approach to async exception safety.+--+-- Since 0.4.10+newtype Resource a = Resource ((forall b. IO b -> IO b) -> IO (Allocated a))+ deriving Typeable++instance Functor Resource where+ fmap = liftM+instance Applicative Resource where+ pure = return+ (<*>) = ap++instance Monad Resource where+ return a = Resource (\_ -> return (Allocated a (return ())))+ Resource f >>= g' = Resource $ \restore -> do+ Allocated x free1 <- f restore+ let Resource g = g' x+ Allocated y free2 <- g restore `E.onException` free1+ return $! Allocated y (free2 `E.finally` free1)++instance MonadIO Resource where+ liftIO f = Resource $ \restore -> do+ x <- restore f+ return $! Allocated x (return ())++instance MonadBase IO Resource where+ liftBase = liftIO++-- | Create a @Resource@ value using the given allocate and free functions.+--+-- Since 0.4.10+mkResource :: IO a -- ^ allocate the resource+ -> (a -> IO ()) -- ^ free the resource+ -> Resource a+mkResource create free = Resource $ \restore -> do+ x <- restore create+ return $! Allocated x (free x)++-- | Allocate the given resource and provide it to the provided function. The+-- resource will be freed as soon as the inner block is exited, whether+-- normally or via an exception. This function is similar in function to+-- @bracket@.+--+-- Since 0.4.10+with :: MonadBaseControl IO m+ => Resource a+ -> (a -> m b)+ -> m b+with (Resource f) g = control $ \run -> E.mask $ \restore -> do+ Allocated x free <- f restore+ run (g x) `E.finally` free
resourcet.cabal view
@@ -1,5 +1,5 @@ Name: resourcet-Version: 0.4.9+Version: 0.4.10 Synopsis: Deterministic allocation and freeing of scarce resources. Description: This package was originally included with the conduit package, and has since been split off. For more information, please see <http://www.yesodweb.com/book/conduits>.