packages feed

conduit 0.2.1 → 0.2.2

raw patch · 5 files changed

+93/−28 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Control.Monad.Trans.Resource: InvalidAccess :: String -> InvalidAccess
+ Control.Monad.Trans.Resource: data InvalidAccess
+ Control.Monad.Trans.Resource: functionName :: InvalidAccess -> String
+ Control.Monad.Trans.Resource: instance Exception InvalidAccess
+ Control.Monad.Trans.Resource: instance Show InvalidAccess
+ Control.Monad.Trans.Resource: instance Typeable InvalidAccess
+ Control.Monad.Trans.Resource: resourceActive :: Resource m => ResourceT m Bool
+ Data.Conduit.List: zip :: Resource m => Source m a -> Source m b -> Source m (a, b)
- Control.Monad.Trans.Resource: transResourceT :: Base m ~ Base n => (m a -> n a) -> ResourceT m a -> ResourceT n a
+ Control.Monad.Trans.Resource: transResourceT :: Base m ~ Base n => (m a -> n b) -> ResourceT m a -> ResourceT n b
- Data.Conduit.Lazy: lazyConsume :: MonadBaseControl IO m => Source m a -> ResourceT m [a]
+ Data.Conduit.Lazy: lazyConsume :: (Resource m, MonadBaseControl IO m) => Source m a -> ResourceT m [a]

Files

Control/Monad/Trans/Resource.hs view
@@ -43,12 +43,14 @@     , ResourceThrow (..)       -- ** Low-level     , HasRef (..)+    , InvalidAccess (..)+    , resourceActive     ) where  import Data.Typeable import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap-import Control.Exception (SomeException)+import Control.Exception (SomeException, throw, Exception) import Control.Monad.Trans.Control     ( MonadTransControl (..), MonadBaseControl (..)     , ComposeSt, defaultLiftBaseWith, defaultRestoreM@@ -260,6 +262,7 @@  data ReleaseMap base =     ReleaseMap !NextKey !RefCount !(IntMap (base ()))+  | ReleaseMapClosed  -- | The Resource transformer. This transformer keeps track of all registered -- actions, and calls them upon exit (via 'runResourceT'). Actions may be@@ -317,11 +320,26 @@           => Ref base (ReleaseMap base)           -> base ()           -> base ReleaseKey-register' istate rel = atomicModifyRef' istate $ \(ReleaseMap key rf m) ->-    ( ReleaseMap (key + 1) rf (IntMap.insert key rel m)-    , ReleaseKey key-    )+register' istate rel = atomicModifyRef' istate $ \rm ->+    case rm of+        ReleaseMap key rf m ->+            ( ReleaseMap (key + 1) rf (IntMap.insert key rel m)+            , ReleaseKey key+            )+        ReleaseMapClosed -> throw $ InvalidAccess "register'" +data InvalidAccess = InvalidAccess { functionName :: String }+    deriving Typeable++instance Show InvalidAccess where+    show (InvalidAccess f) = concat+        [ "Control.Monad.Trans.Resource."+        , f+        , ": The mutable state is being accessed after cleanup. Please contact the maintainers."+        ]++instance Exception InvalidAccess+ -- | Call a release action early, and deregister it from the list of cleanup -- actions to be performed. release :: Resource m@@ -344,25 +362,30 @@                 ( ReleaseMap next rf $ IntMap.delete key m                 , Just action                 )+    lookupAction ReleaseMapClosed = throw $ InvalidAccess "release'"  stateAlloc :: HasRef m => Ref m (ReleaseMap m) -> m () stateAlloc istate = do-    atomicModifyRef' istate $ \(ReleaseMap nk rf m) ->-        (ReleaseMap nk (rf + 1) m, ())+    atomicModifyRef' istate $ \rm ->+        case rm of+            ReleaseMap nk rf m ->+                (ReleaseMap nk (rf + 1) m, ())+            ReleaseMapClosed -> throw $ InvalidAccess "stateAlloc"  stateCleanup :: HasRef m => Ref m (ReleaseMap m) -> m () stateCleanup istate = mask_ $ do-    (rf, m) <- atomicModifyRef' istate $ \(ReleaseMap nk rf m) ->-        (ReleaseMap nk (rf - 1) m, (rf - 1, m))-    if rf == minBound-        then do+    mm <- atomicModifyRef' istate $ \rm ->+        case rm of+            ReleaseMap nk rf m ->+                let rf' = rf - 1+                 in if rf' == minBound+                        then (ReleaseMapClosed, Just m)+                        else (ReleaseMap nk rf' m, Nothing)+            ReleaseMapClosed -> throw $ InvalidAccess "stateCleanup"+    case mm of+        Just m ->             mapM_ (\x -> try x >> return ()) $ IntMap.elems m-            -- Trigger an exception consistently for one race condition:-            -- let's put an undefined value in the state. If somehow-            -- another thread is still able to access it, at least we get-            -- clearer error messages.-            writeRef' istate $ error "Control.Monad.Trans.Resource.stateCleanup: There is a bug in the implementation. The mutable state is being accessed after cleanup. Please contact the maintainers."-        else return ()+        Nothing -> return ()  -- | Unwrap a 'ResourceT' transformer, and call all registered release actions. --@@ -382,9 +405,9 @@ -- strip or add new transformers to a stack, e.g. to run a @ReaderT@. Note that -- the original and new monad must both have the same 'Base' monad. transResourceT :: (Base m ~ Base n)-               => (m a -> n a)+               => (m a -> n b)                -> ResourceT m a-               -> ResourceT n a+               -> ResourceT n b transResourceT f (ResourceT mx) = ResourceT (\r -> f (mx r))  -------- All of our monad et al instances@@ -523,3 +546,13 @@             (return ())             (stateCleanup r)             (restore $ f r))++-- | Determine if the current @ResourceT@ is still active. This is necessary+-- for such cases as lazy I\/O, where an unevaluated thunk may still refer to a+-- closed @ResourceT@.+resourceActive :: Resource m => ResourceT m Bool+resourceActive = ResourceT $ \rmMap -> do+    rm <- resourceLiftBase $ readRef' rmMap+    case rm of+        ReleaseMapClosed -> return False+        _ -> return True
Data/Conduit/Lazy.hs view
@@ -8,20 +8,25 @@  import Data.Conduit import System.IO.Unsafe (unsafeInterleaveIO)-import Control.Monad.Trans.Control+import Control.Monad.Trans.Control (MonadBaseControl, liftBaseOp_)+import Control.Monad.Trans.Resource (resourceActive)  -- | Use lazy I\/O to consume all elements from a @Source@. -- -- Since 0.2.0-lazyConsume :: MonadBaseControl IO m => Source m a -> ResourceT m [a]+lazyConsume :: (Resource m, MonadBaseControl IO m) => Source m a -> ResourceT m [a] lazyConsume src0 = do     go src0   where      go src = liftBaseOp_ unsafeInterleaveIO $ do-        res <- sourcePull src-        case res of-            Closed -> return []-            Open src' x -> do-                y <- go src'-                return $ x : y+        ra <- resourceActive+        if ra+            then do+                res <- sourcePull src+                case res of+                    Closed -> return []+                    Open src' x -> do+                        y <- go src'+                        return $ x : y+            else return []
Data/Conduit/List.hs view
@@ -18,6 +18,7 @@     , take     , drop     , head+    , zip     , peek     , consume     , sinkNull@@ -322,3 +323,20 @@ -- Since 0.2.0 sourceNull :: Resource m => Source m a sourceNull = mempty++-- | Combines two sources. The new source will stop producing once either+--   source has been exhausted.+--+-- Since 0.2.2+zip :: Resource m => Source m a -> Source m b -> Source m (a, b)+zip sa sb = Source pull close+    where+        pull = do ra <- sourcePull sa+                  case ra of+                    Closed -> return Closed+                    Open ra' a -> do rb <- sourcePull sb+                                     case rb of+                                        Closed -> return Closed+                                        Open rb' b -> return $ Open (zip ra' rb') (a, b)+        close = sourceClose sa >> sourceClose sb+
conduit.cabal view
@@ -1,5 +1,5 @@ Name:                conduit-Version:             0.2.1+Version:             0.2.2 Synopsis:            Streaming data processing library. Description: 	Conduits are an approach to the streaming data problem. It is meant as an alternative to enumerators\/iterators, hoping to address the same issues with different trade-offs based on real-world experience with enumerators. For more information, see <http://www.yesodweb.com/book/conduit>.
test/main.hs view
@@ -121,6 +121,11 @@             bs1 @=? bs2             bs1 @=? bs3 +    describe "zipping" $ do+        it "zipping two small lists" $ do+            res <- runResourceT $ CL.zip (CL.sourceList [1..10]) (CL.sourceList [11..12]) C.$$ CL.consume+            res @=? zip [1..10 :: Int] [11..12 :: Int]+     describe "Monad instance for Sink" $ do         it "binding" $ do             x <- runResourceT $ CL.sourceList [1..10] C.$$ do@@ -242,6 +247,10 @@                             )             nums <- CLazy.lazyConsume $ mconcat $ map incr [1..10]             liftIO $ nums @?= [1..10]++        it' "returns nothing outside ResourceT" $ do+            bss <- runResourceT $ CLazy.lazyConsume $ CB.sourceFile "test/main.hs"+            bss @?= []      describe "sequence" $ do         it "simple sink" $ do