pipes-safe 2.2.0 → 2.2.1
raw patch · 4 files changed
+120/−31 lines, 4 filesdep ~exceptionsPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: exceptions
API changes (from Hackage documentation)
Files
- README.md +84/−0
- changelog.md +3/−0
- pipes-safe.cabal +3/−2
- src/Pipes/Safe.hs +30/−29
+ README.md view
@@ -0,0 +1,84 @@+# Pipes-Safe v2.2.0++`pipes-safe` builds upon+[the `pipes` library](https://github.com/Gabriel439/Haskell-Pipes-Library) to+provide exception safety and resource management.++## Quick start++* Install the [Haskell Platform](http://www.haskell.org/platform/)+* `cabal install pipes-safe`++The official tutorial is on+[Hackage](http://hackage.haskell.org/package/pipes-safe).++## Features++* *Resource Safety*: Guarantee finalization using `finally`, `bracket`, and more++* *Exception Safety*: Even against asynchronous exceptions!++* *Laziness*: Only acquire resources when you need them++* *Promptness*: Finalize resources early when you are done with them++* *Native Exception Handling*: Catch and resume from exceptions inside pipes++* *No Buy-in*: Mix resource-safe pipes with unmanaged pipes using `hoist`++## Outline++Use `pipes-safe` for production code where you need deterministic and prompt+release of resources in the fact of exceptions or premature pipe termination.+`pipes-safe` lets you safely acquire resources and handle exceptions within+pipelines.++## Development Status++`pipes-safe` is mostly stable. Research into prompter finalization alternatives+will take place in a separate library.++## Community Resources++Use the same resources as the core `pipes` library to learn more, contribute, or+request help:++* [Haskell wiki page](http://www.haskell.org/haskellwiki/Pipes)++* [Mailing list](mailto:haskell-pipes@googlegroups.com) ([Google Group](https://groups.google.com/forum/?fromgroups#!forum/haskell-pipes))++## How to contribute++* Build derived libraries++* Write `pipes-safe` tutorials++## License (BSD 3-clause)++Copyright (c) 2013 Gabriel Gonzalez+All rights reserved.++Redistribution and use in source and binary forms, with or without modification,+are permitted provided that the following conditions are met:++* Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++* Redistributions in binary form must reproduce the above copyright notice, this+ list of conditions and the following disclaimer in the documentation and/or+ other materials provided with the distribution.++* Neither the name of Gabriel Gonzalez nor the names of other contributors may+ be used to endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ changelog.md view
@@ -0,0 +1,3 @@+# Version 2.2.1++* Raise upper-bound on `exceptions` dependency.
pipes-safe.cabal view
@@ -1,9 +1,10 @@ Name: pipes-safe-Version: 2.2.0+Version: 2.2.1 Cabal-Version: >=1.8.0.2 Build-Type: Simple License: BSD3 License-File: LICENSE+Extra-Source-Files: README.md changelog.md Copyright: 2013, 2014 Gabriel Gonzalez Author: Gabriel Gonzalez Maintainer: Gabriel439@gmail.com@@ -36,7 +37,7 @@ Build-Depends: base >= 4 && < 5 , containers >= 0.3.0.0 && < 0.6,- exceptions >= 0.6 && < 0.7,+ exceptions >= 0.6 && < 0.8, transformers >= 0.2.0.0 && < 0.5, pipes >= 4.0.0 && < 4.2 Exposed-Modules:
src/Pipes/Safe.hs view
@@ -123,7 +123,7 @@ import qualified Data.Map as M import Data.Monoid (Monoid) import Pipes (Proxy, Effect, Effect', runEffect)-import Pipes.Internal (unsafeHoist, Proxy(..))+import Pipes.Internal (Proxy(..)) import Pipes.Lift (liftCatchError) data Restore m = Unmasked | Masked (forall x . m x -> m x)@@ -134,34 +134,35 @@ -> ((forall x . Proxy a' a b' b m x -> Proxy a' a b' b m x) -> Proxy a' a b' b m r) -> Proxy a' a b' b m r-liftMask maskFunction k = do- ioref <- liftIO (newIORef Unmasked)- let unmask- :: forall y . (Monad m)- => Proxy a' a b' b m y -> Proxy a' a b' b m y- unmask p = do- mRestore <- liftIO (readIORef ioref)- case mRestore of- Unmasked -> p- Masked restore -> do- r <- unsafeHoist restore p- lift $ restore $ return ()- return r- loop p = case p of- Request a' fa -> Request a' (loop . fa )- Respond b fb' -> Respond b (loop . fb')- M m0 -> M $ maskFunction $ \restore -> do- liftIO $ writeIORef ioref (Masked restore)- let loop' m = do- p' <- m- case p' of- M m' -> loop' m'- _ -> return p'- p' <- loop' m0- liftIO $ writeIORef ioref Unmasked- return (loop p')- Pure r -> Pure r- loop (k unmask)+liftMask maskVariant k = do+ ioref <- liftIO $ newIORef Unmasked++ let -- mask adjacent actions in base monad+ loop :: Proxy a' a b' b m r -> Proxy a' a b' b m r+ loop (Request a' fa ) = Request a' (loop . fa )+ loop (Respond b fb') = Respond b (loop . fb')+ loop (M m) = M $ maskVariant $ \unmaskVariant -> do+ -- stash base's unmask and merge action+ liftIO $ writeIORef ioref $ Masked unmaskVariant+ m >>= chunk >>= return . loop+ loop (Pure r) = Pure r++ -- unmask adjacent actions in base monad+ unmask :: forall q. Proxy a' a b' b m q -> Proxy a' a b' b m q+ unmask (Request a' fa ) = Request a' (unmask . fa )+ unmask (Respond b fb') = Respond b (unmask . fb')+ unmask (M m) = M $ do+ -- retrieve base's unmask and apply to merged action+ Masked unmaskVariant <- liftIO $ readIORef ioref+ unmaskVariant (m >>= chunk >>= return . unmask)+ unmask (Pure q) = Pure q++ -- merge adjacent actions in base monad+ chunk :: forall s. Proxy a' a b' b m s -> m (Proxy a' a b' b m s)+ chunk (M m) = m >>= chunk+ chunk s = return s++ loop $ k unmask instance (MonadThrow m) => MonadThrow (Proxy a' a b' b m) where throwM = lift . throwM