@@ -14,7 +14,7 @@ module Streamly.Internal.Data.Stream.StreamD.Exception
1414 , after_
1515 , after
1616 , bracket_
17− , bracket
17+ , bracket'
1818 , onException
1919 , finally_
2020 , finally
@@ -101,7 +101,9 @@ data GbracketIOState s1 s2 v wref
101101-- output @c@ as input to @c -> Stream m b@ to generate an output stream. When
102102-- generating the stream use the supplied @try@ operation @forall s. m s -> m
103103-- (Either e s)@ to catch synchronous exceptions. If an exception occurs run
104−-- the exception handler @c -> e -> Stream m b -> m (Stream m b)@.
104+-- the exception handler @c -> e -> Stream m b -> m (Stream m b)@. Note that
105+-- 'gbracket' does not rethrow the exception, it has to be done by the
106+-- exception handler if desired.
105107--
106108-- The cleanup action @c -> m d@, runs whenever the stream ends normally, due
107109-- to a sync or async exception or if it gets garbage collected after a partial
@@ -115,13 +117,14 @@ data GbracketIOState s1 s2 v wref
115117{-# INLINE_NORMAL gbracket #-}
116118gbracket
117119 :: (MonadIO m, MonadBaseControl IO m)
118− => m c -- ^ before
119− -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
120− -> (c -> m d) -- ^ after, on normal stop or GC
120+ => m c -- ^ before
121+ -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
122+ -> (c -> m d1) -- ^ on normal stop
123+ -> (c -> m d2) -- ^ on GC without normal stop or exception
121124 -> (c -> e -> Stream m b -> m (Stream m b)) -- ^ on exception
122− -> (c -> Stream m b) -- ^ stream generator
125+ -> (c -> Stream m b) -- ^ stream generator
123126 -> Stream m b
124−gbracket bef exc aft fexc fnormal =
127+gbracket bef exc aft gc fexc fnormal =
125128 Stream step GBracketIOInit
126129
127130 where
@@ -137,7 +140,7 @@ gbracket bef exc aft fexc fnormal =
137140 -- Tutorial: https://markkarpov.com/tutorial/exceptions.html
138141 (r, ref) <- liftBaseOp_ mask_ $ do
139142 r <- bef
140− ref <- newIOFinalizer (aft r)
143+ ref <- newIOFinalizer (gc r)
141144 return (r, ref)
142145 return $ Skip $ GBracketIONormal (fnormal r) r ref
143146
@@ -149,9 +152,8 @@ gbracket bef exc aft fexc fnormal =
149152 return $ Yield x (GBracketIONormal (Stream step1 s) v ref)
150153 Skip s ->
151154 return $ Skip (GBracketIONormal (Stream step1 s) v ref)
152− Stop -> do
153− runIOFinalizer ref
154− return Stop
155+ Stop ->
156+ clearingIOFinalizer ref (aft v) >> return Stop
155157 -- XXX Do not handle async exceptions, just rethrow them.
156158 Left e -> do
157159 -- Clearing of finalizer and running of exception handler must
@@ -261,12 +263,17 @@ bracket_ bef aft bet =
261263
262264-- | See 'Streamly.Internal.Data.Stream.IsStream.bracket'.
263265--
264−{-# INLINE_NORMAL bracket #-}
265−bracket :: (MonadAsync m, MonadCatch m)
266− => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
267−bracket bef aft bet =
268− gbracket bef (inline MC.try) aft
269− (\a (e :: SomeException) _ -> aft a >> return (nilM (MC.throwM e))) bet
266+{-# INLINE_NORMAL bracket' #-}
267+bracket' :: (MonadAsync m, MonadCatch m) =>
268+ m b
269+ -> (b -> m c)
270+ -> (b -> m d)
271+ -> (b -> m e)
272+ -> (b -> Stream m a)
273+ -> Stream m a
274+bracket' bef aft exc gc =
275+ gbracket bef (inline MC.try) aft gc
276+ (\a (e :: SomeException) _ -> exc a >> return (nilM (MC.throwM e)))
270277
271278data BracketState s v = BracketInit | BracketRun s v
272279
@@ -306,7 +313,8 @@ finally_ action xs = bracket_ (return ()) (\_ -> action) (const xs)
306313--
307314{-# INLINE finally #-}
308315finally :: (MonadAsync m, MonadCatch m) => m b -> Stream m a -> Stream m a
309−finally action xs = bracket (return ()) (\_ -> action) (const xs)
316+finally action xs = bracket' (return ()) act act act (const xs)
317+ where act _ = action
310318
311319-- | See 'Streamly.Internal.Data.Stream.IsStream.ghandle'.
312320--