@@ -36,6 +36,7 @@ import Control.Monad.IO.Class (MonadIO(..))
36import Control.Monad.Reader.Class (MonadReader(..))
36import Control.Monad.Reader.Class (MonadReader(..))
37import Control.Monad.State.Class (MonadState(..))
37import Control.Monad.State.Class (MonadState(..))
38import Control.Monad.Trans.Class (MonadTrans(lift))
38import Control.Monad.Trans.Class (MonadTrans(lift))
39+import Control.Monad.Trans.Control (MonadBaseControl (..))
39import Data.Heap (Heap, Entry(..))
40import Data.Heap (Heap, Entry(..))
40import Data.IORef (IORef, readIORef, atomicModifyIORef, writeIORef)
41import Data.IORef (IORef, readIORef, atomicModifyIORef, writeIORef)
41import Data.Maybe (fromJust)
42import Data.Maybe (fromJust)
@@ -49,8 +50,7 @@ import qualified Data.Heap as H
49import Streamly.Internal.Data.Stream.SVar (fromSVar)
50import Streamly.Internal.Data.Stream.SVar (fromSVar)
50import Streamly.Internal.Data.SVar
51import Streamly.Internal.Data.SVar
51import Streamly.Internal.Data.Stream.StreamK
52import Streamly.Internal.Data.Stream.StreamK
52− (IsStream(..), Stream, mkStream, foldStream, foldStreamShared,
53+ (IsStream(..), Stream, mkStream, foldStream, foldStreamShared)
54import qualified Streamly.Internal.Data.Stream.StreamK as K
54import qualified Streamly.Internal.Data.Stream.StreamK as K
55import qualified Streamly.Internal.Data.Stream.StreamD as D
55import qualified Streamly.Internal.Data.Stream.StreamD as D
@@ -212,7 +212,8 @@ abortExecution q sv winfo m = do
213-- In both cases we give the drainer a chance to run more often.
213-- In both cases we give the drainer a chance to run more often.
215−processHeap :: MonadIO m
215+processHeap
216+ :: (MonadIO m, MonadBaseControl IO m)
216 => IORef ([Stream m a], Int)
217 => IORef ([Stream m a], Int)
217 -> IORef (Heap (Entry Int (AheadHeapEntry Stream m a)), Maybe Int)
218 -> IORef (Heap (Entry Int (AheadHeapEntry Stream m a)), Maybe Int)
218 -> State Stream m a
219 -> State Stream m a
@@ -316,7 +317,8 @@ processHeap q heap st sv winfo entry sno stopping = loopHeap sno entry
316 runStreamWithYieldLimit continue seqNo r
317 runStreamWithYieldLimit continue seqNo r
318{-# NOINLINE drainHeap #-}
319{-# NOINLINE drainHeap #-}
319−drainHeap :: MonadIO m
320+drainHeap
321+ :: (MonadIO m, MonadBaseControl IO m)
320 => IORef ([Stream m a], Int)
322 => IORef ([Stream m a], Int)
321 -> IORef (Heap (Entry Int (AheadHeapEntry Stream m a)), Maybe Int)
323 -> IORef (Heap (Entry Int (AheadHeapEntry Stream m a)), Maybe Int)
322 -> State Stream m a
324 -> State Stream m a
@@ -331,8 +333,10 @@ drainHeap q heap st sv winfo = do
331 _ -> liftIO $ sendStop sv winfo
333 _ -> liftIO $ sendStop sv winfo
333data HeapStatus = HContinue | HStop
335data HeapStatus = HContinue | HStop
336+data WorkerStatus = Continue | Suspend
335−processWithoutToken :: MonadIO m
338+processWithoutToken
339+ :: (MonadIO m, MonadBaseControl IO m)
336 => IORef ([Stream m a], Int)
340 => IORef ([Stream m a], Int)
337 -> IORef (Heap (Entry Int (AheadHeapEntry Stream m a)), Maybe Int)
341 -> IORef (Heap (Entry Int (AheadHeapEntry Stream m a)), Maybe Int)
338 -> State Stream m a
342 -> State Stream m a
@@ -351,12 +355,18 @@ processWithoutToken q heap st sv winfo m seqNo = do
351 -- put it on heap. So we have to put a null entry on heap even when
355 -- put it on heap. So we have to put a null entry on heap even when
352 -- we stop.
356 -- we stop.
353 toHeap AheadEntryNull
357 toHeap AheadEntryNull
358+ mrun = runInIO $ svarMrun sv
355− foldStreamSVar sv st
360+ r <- liftIO $ mrun $
356− (\a r -> toHeap $ AheadEntryStream $ K.cons a r)
362+ (\a r -> toHeap $ AheadEntryStream $ K.cons a r)
357− (toHeap . AheadEntryPure)
363+ (toHeap . AheadEntryPure)
368+ Continue -> workLoopAhead q heap st sv winfo
369+ Suspend -> drainHeap q heap st sv winfo
@@ -377,8 +387,6 @@ processWithoutToken q heap st sv winfo m seqNo = do
377 writeIORef (maxHeapSize $ svarStats sv) (H.size newHp)
387 writeIORef (maxHeapSize $ svarStats sv) (H.size newHp)
379 heapOk <- liftIO $ underMaxHeap sv newHp
389 heapOk <- liftIO $ underMaxHeap sv newHp
380− let drainAndStop = drainHeap q heap st sv winfo
381− mainLoop = workLoopAhead q heap st sv winfo
382 status <-
390 status <-
383 case yieldRateInfo sv of
391 case yieldRateInfo sv of
384 Nothing -> return HContinue
392 Nothing -> return HContinue
@@ -394,11 +402,14 @@ processWithoutToken q heap st sv winfo m seqNo = do
394 if heapOk
402 if heapOk
396 case status of
404 case status of
397− HContinue -> mainLoop
405+ HContinue -> return Continue
398− HStop -> drainAndStop
406+ HStop -> return Suspend
399− else drainAndStop
407+ else return Suspend
409+data TokenWorkerStatus = TokenContinue Int | TokenSuspend
401−processWithToken :: MonadIO m
411+processWithToken
412+ :: (MonadIO m, MonadBaseControl IO m)
402 => IORef ([Stream m a], Int)
413 => IORef ([Stream m a], Int)
403 -> IORef (Heap (Entry Int (AheadHeapEntry Stream m a)), Maybe Int)
414 -> IORef (Heap (Entry Int (AheadHeapEntry Stream m a)), Maybe Int)
404 -> State Stream m a
415 -> State Stream m a
@@ -412,19 +423,26 @@ processWithToken q heap st sv winfo action sno = do
412 -- XXX deduplicate stop in all invocations
423 -- XXX deduplicate stop in all invocations
413 let stop = do
424 let stop = do
414 liftIO (incrementYieldLimit sv)
425 liftIO (incrementYieldLimit sv)
415− loopWithToken (sno + 1)
426+ return $ TokenContinue (sno + 1)
427+ mrun = runInIO $ svarMrun sv
429+ r <- liftIO $ mrun $
417− foldStreamSVar sv st (yieldOutput sno) (singleOutput sno) stop action
430+ foldStreamShared st (yieldOutput sno) (singleOutput sno) stop action
434+ TokenContinue seqNo -> loopWithToken seqNo
435+ TokenSuspend -> drainHeap q heap st sv winfo
421 singleOutput seqNo a = do
439 singleOutput seqNo a = do
422 continue <- liftIO $ sendYield sv winfo (ChildYield a)
440 continue <- liftIO $ sendYield sv winfo (ChildYield a)
423 if continue
441 if continue
424− then loopWithToken (seqNo + 1)
442+ then return $ TokenContinue (seqNo + 1)
426 liftIO $ updateHeapSeq heap (seqNo + 1)
444 liftIO $ updateHeapSeq heap (seqNo + 1)
427− drainHeap q heap st sv winfo
445+ return TokenSuspend
429 -- XXX use a wrapper function around stop so that we never miss
447 -- XXX use a wrapper function around stop so that we never miss
430 -- incrementing the yield in a stop continuation. Essentiatlly all
448 -- incrementing the yield in a stop continuation. Essentiatlly all
@@ -436,7 +454,7 @@ processWithToken q heap st sv winfo action sno = do
437 let stop = do
455 let stop = do
438 liftIO (incrementYieldLimit sv)
456 liftIO (incrementYieldLimit sv)
439− loopWithToken (seqNo + 1)
457+ return $ TokenContinue (seqNo + 1)
440 foldStreamShared st
458 foldStreamShared st
441 (yieldOutput seqNo)
459 (yieldOutput seqNo)
442 (singleOutput seqNo)
460 (singleOutput seqNo)
@@ -446,7 +464,7 @@ processWithToken q heap st sv winfo action sno = do
446 let ent = Entry seqNo (AheadEntryStream r)
464 let ent = Entry seqNo (AheadEntryStream r)
447 liftIO $ requeueOnHeapTop heap ent seqNo
465 liftIO $ requeueOnHeapTop heap ent seqNo
448 liftIO $ incrementYieldLimit sv
466 liftIO $ incrementYieldLimit sv
449− drainHeap q heap st sv winfo
467+ return TokenSuspend
451 loopWithToken nextSeqNo = do
469 loopWithToken nextSeqNo = do
452 work <- dequeueAhead q
470 work <- dequeueAhead q
@@ -467,12 +485,19 @@ processWithToken q heap st sv winfo action sno = do
468 let stop = do
486 let stop = do
469 liftIO (incrementYieldLimit sv)
487 liftIO (incrementYieldLimit sv)
470− loopWithToken (seqNo + 1)
488+ return $ TokenContinue (seqNo + 1)
489+ mrun = runInIO $ svarMrun sv
490+ r <- liftIO $ mrun $
471− foldStreamShared st
491+ foldStreamShared st
472− (yieldOutput seqNo)
492+ (yieldOutput seqNo)
473− (singleOutput seqNo)
493+ (singleOutput seqNo)
498+ TokenContinue seqNo1 -> loopWithToken seqNo1
499+ TokenSuspend -> drainHeap q heap st sv winfo
477 -- To avoid a race when another thread puts something
502 -- To avoid a race when another thread puts something
478 -- on the heap and goes away, the consumer will not get
503 -- on the heap and goes away, the consumer will not get
@@ -496,7 +521,8 @@ processWithToken q heap st sv winfo action sno = do
497-- XXX we can remove the sv parameter as it can be derived from st
522-- XXX we can remove the sv parameter as it can be derived from st
499−workLoopAhead :: MonadIO m
524+workLoopAhead
525+ :: (MonadIO m, MonadBaseControl IO m)
500 => IORef ([Stream m a], Int)
526 => IORef ([Stream m a], Int)
501 -> IORef (Heap (Entry Int (AheadHeapEntry Stream m a)), Maybe Int)
527 -> IORef (Heap (Entry Int (AheadHeapEntry Stream m a)), Maybe Int)
502 -> State Stream m a
528 -> State Stream m a