@@ -39,6 +39,7 @@ where
3939import Control.Concurrent (myThreadId)
4040import Control.Monad.Base (MonadBase(..), liftBaseDefault)
4141import Control.Monad.Catch (MonadThrow, throwM)
42+import Control.Monad.Trans.Control (MonadBaseControl (..))
4243import Control.Concurrent.MVar (newEmptyMVar)
4344-- import Control.Monad.Error.Class (MonadError(..))
4445import Control.Monad.IO.Class (MonadIO(..))
@@ -59,8 +60,7 @@ import Streamly.Internal.Data.Atomics (atomicModifyIORefCAS)
5960import Streamly.Internal.Data.Stream.SVar (fromSVar)
6061import Streamly.Internal.Data.SVar
6162import Streamly.Internal.Data.Stream.StreamK
62− (IsStream(..), Stream, mkStream, foldStream, adapt, foldStreamShared,
63− foldStreamSVar)
63+ (IsStream(..), Stream, mkStream, foldStream, adapt, foldStreamShared)
6464import qualified Streamly.Internal.Data.Stream.StreamK as K
6565import qualified Streamly.Internal.Data.Stream.StreamD as D
6666
@@ -70,9 +70,11 @@ import qualified Streamly.Internal.Data.Stream.StreamD as D
7070-- Async
7171-------------------------------------------------------------------------------
7272
73+data WorkerStatus = Continue | Suspend
74+
7375{-# INLINE workLoopLIFO #-}
7476workLoopLIFO
75− :: MonadIO m
77+ :: (MonadIO m, MonadBaseControl IO m)
7678 => IORef [Stream m a]
7779 -> State Stream m a
7880 -> SVar Stream m a
@@ -82,23 +84,39 @@ workLoopLIFO q st sv winfo = run
8284
8385 where
8486
87+ mrun = runInIO $ svarMrun sv
8588 run = do
8689 work <- dequeue
90+ let stop = liftIO $ sendStop sv winfo
8791 case work of
88− Nothing -> liftIO $ sendStop sv winfo
89− Just m -> foldStreamSVar sv st yieldk single run m
92+ Nothing -> stop
93+ Just m -> do
94+ -- XXX when we finish we need to send the monadic state back to
95+ -- the parent so that the state can be merged back. We capture
96+ -- and return the state in the stop continuation.
97+ --
98+ -- Instead of using the run function we can just restore the
99+ -- monad state here. That way it can work easily for
100+ -- distributed case as well.
101+ r <- liftIO $ mrun $
102+ foldStreamShared st yieldk single (return Continue) m
103+ res <- restoreM r
104+ case res of
105+ Continue -> run
106+ Suspend -> stop
90107
91108 single a = do
92109 res <- liftIO $ sendYield sv winfo (ChildYield a)
93− if res then run else liftIO $ sendStop sv winfo
110+ return $ if res then Continue else Suspend
94111
95112 yieldk a r = do
96113 res <- liftIO $ sendYield sv winfo (ChildYield a)
97114 if res
98− then foldStreamShared st yieldk single run r
115+ then foldStreamShared st yieldk single (return Continue) r
99116 else liftIO $ do
117+ -- XXX we also need to save the monadic state here
100118 enqueueLIFO sv q r
101− sendStop sv winfo
119+ return Suspend
102120
103121 dequeue = liftIO $ atomicModifyIORefCAS q $ \case
104122 [] -> ([], Nothing)
@@ -111,7 +129,7 @@ workLoopLIFO q st sv winfo = run
111129-- make a check every time.
112130{-# INLINE workLoopLIFOLimited #-}
113131workLoopLIFOLimited
114− :: MonadIO m
132+ :: (MonadIO m, MonadBaseControl IO m)
115133 => IORef [Stream m a]
116134 -> State Stream m a
117135 -> SVar Stream m a
@@ -121,10 +139,13 @@ workLoopLIFOLimited q st sv winfo = run
121139
122140 where
123141
142+ mrun = runInIO $ svarMrun sv
143+ incrContinue = liftIO (incrementYieldLimit sv) >> return Continue
124144 run = do
125145 work <- dequeue
146+ let stop = liftIO $ sendStop sv winfo
126147 case work of
127− Nothing -> liftIO $ sendStop sv winfo
148+ Nothing -> stop
128149 Just m -> do
129150 -- XXX This is just a best effort minimization of concurrency
130151 -- to the yield limit. If the stream is made of concurrent
@@ -135,8 +156,12 @@ workLoopLIFOLimited q st sv winfo = run
135156 yieldLimitOk <- liftIO $ decrementYieldLimit sv
136157 if yieldLimitOk
137158 then do
138− let stop = liftIO (incrementYieldLimit sv) >> run
139− foldStreamSVar sv st yieldk single stop m
159+ r <- liftIO $ mrun $
160+ foldStreamShared st yieldk single incrContinue m
161+ res <- restoreM r
162+ case res of
163+ Continue -> run
164+ Suspend -> stop
140165 -- Avoid any side effects, undo the yield limit decrement if we
141166 -- never yielded anything.
142167 else liftIO $ do
@@ -146,20 +171,19 @@ workLoopLIFOLimited q st sv winfo = run
146171
147172 single a = do
148173 res <- liftIO $ sendYield sv winfo (ChildYield a)
149− if res then run else liftIO $ sendStop sv winfo
174+ return $ if res then Continue else Suspend
150175
151176 -- XXX can we pass on the yield limit downstream to limit the concurrency
152177 -- of constituent streams.
153178 yieldk a r = do
154179 res <- liftIO $ sendYield sv winfo (ChildYield a)
155180 yieldLimitOk <- liftIO $ decrementYieldLimit sv
156− let stop = liftIO (incrementYieldLimit sv) >> run
157181 if res && yieldLimitOk
158− then foldStreamShared st yieldk single stop r
182+ then foldStreamShared st yieldk single incrContinue r
159183 else liftIO $ do
160184 incrementYieldLimit sv
161185 enqueueLIFO sv q r
162− sendStop sv winfo
186+ return Suspend
163187
164188 dequeue = liftIO $ atomicModifyIORefCAS q $ \case
165189 [] -> ([], Nothing)
@@ -173,7 +197,7 @@ workLoopLIFOLimited q st sv winfo = run
173197
174198{-# INLINE workLoopFIFO #-}
175199workLoopFIFO
176− :: MonadIO m
200+ :: (MonadIO m, MonadBaseControl IO m)
177201 => LinkedQueue (Stream m a)
178202 -> State Stream m a
179203 -> SVar Stream m a
@@ -183,27 +207,35 @@ workLoopFIFO q st sv winfo = run
183207
184208 where
185209
210+ mrun = runInIO $ svarMrun sv
186211 run = do
187212 work <- liftIO $ tryPopR q
213+ let stop = liftIO $ sendStop sv winfo
188214 case work of
189− Nothing -> liftIO $ sendStop sv winfo
190− Just m -> foldStreamSVar sv st yieldk single run m
215+ Nothing -> stop
216+ Just m -> do
217+ r <- liftIO $ mrun $
218+ foldStreamShared st yieldk single (return Continue) m
219+ res <- restoreM r
220+ case res of
221+ Continue -> run
222+ Suspend -> stop
191223
192224 single a = do
193225 res <- liftIO $ sendYield sv winfo (ChildYield a)
194− if res then run else liftIO $ sendStop sv winfo
226+ return $ if res then Continue else Suspend
195227
196228 yieldk a r = do
197229 res <- liftIO $ sendYield sv winfo (ChildYield a)
198230 if res
199− then foldStreamShared st yieldk single run r
231+ then foldStreamShared st yieldk single (return Continue) r
200232 else liftIO $ do
201233 enqueueFIFO sv q r
202− sendStop sv winfo
234+ return Suspend
203235
204236{-# INLINE workLoopFIFOLimited #-}
205237workLoopFIFOLimited
206− :: MonadIO m
238+ :: (MonadIO m, MonadBaseControl IO m)
207239 => LinkedQueue (Stream m a)
208240 -> State Stream m a
209241 -> SVar Stream m a
@@ -213,16 +245,23 @@ workLoopFIFOLimited q st sv winfo = run
213245
214246 where
215247
248+ mrun = runInIO $ svarMrun sv
249+ incrContinue = liftIO (incrementYieldLimit sv) >> return Continue
216250 run = do
217251 work <- liftIO $ tryPopR q
252+ let stop = liftIO $ sendStop sv winfo
218253 case work of
219− Nothing -> liftIO $ sendStop sv winfo
254+ Nothing -> stop
220255 Just m -> do
221256 yieldLimitOk <- liftIO $ decrementYieldLimit sv
222257 if yieldLimitOk
223258 then do
224− let stop = liftIO (incrementYieldLimit sv) >> run
225− foldStreamSVar sv st yieldk single stop m
259+ r <- liftIO $ mrun $
260+ foldStreamShared st yieldk single incrContinue m
261+ res <- restoreM r
262+ case res of
263+ Continue -> run
264+ Suspend -> stop
226265 else liftIO $ do
227266 enqueueFIFO sv q m
228267 incrementYieldLimit sv
@@ -230,18 +269,17 @@ workLoopFIFOLimited q st sv winfo = run
230269
231270 single a = do
232271 res <- liftIO $ sendYield sv winfo (ChildYield a)
233− if res then run else liftIO $ sendStop sv winfo
272+ return $ if res then Continue else Suspend
234273
235274 yieldk a r = do
236275 res <- liftIO $ sendYield sv winfo (ChildYield a)
237276 yieldLimitOk <- liftIO $ decrementYieldLimit sv
238− let stop = liftIO (incrementYieldLimit sv) >> run
239277 if res && yieldLimitOk
240− then foldStreamShared st yieldk single stop r
278+ then foldStreamShared st yieldk single incrContinue r
241279 else liftIO $ do
242280 incrementYieldLimit sv
243281 enqueueFIFO sv q r
244− sendStop sv winfo
282+ return Suspend
245283
246284-------------------------------------------------------------------------------
247285-- SVar creation