@@ -52,6 +52,7 @@ module Streamly.SVar
5252 , atomicModifyIORefCAS
5353 , WorkerInfo (..)
5454 , YieldRateInfo (..)
55+ , ThreadAbort (..)
5556 , ChildEvent (..)
5657 , AheadHeapEntry (..)
5758 , send
@@ -74,6 +75,7 @@ module Streamly.SVar
7475 , workerRateControl
7576 , updateYieldCount
7677 , decrementYieldLimit
78+ , decrementYieldLimitPost
7779 , incrementYieldLimit
7880 , postProcessBounded
7981 , postProcessPaced
@@ -96,7 +98,7 @@ import Control.Concurrent
9698 (ThreadId, myThreadId, threadDelay, getNumCapabilities)
9799import Control.Concurrent.MVar
98100 (MVar, newEmptyMVar, tryPutMVar, takeMVar, newMVar)
99−import Control.Exception (SomeException(..), catch, mask, assert)
101+import Control.Exception (SomeException(..), catch, mask, assert, Exception)
100102import Control.Monad (when)
101103import Control.Monad.Catch (MonadThrow)
102104import Control.Monad.IO.Class (MonadIO(..))
@@ -163,6 +165,10 @@ newtype Count = Count Word64
163165-- Parent child thread communication type
164166------------------------------------------------------------------------------
165167
168+data ThreadAbort = ThreadAbort deriving Show
169+
170+instance Exception ThreadAbort
171+
166172-- | Events that a child thread may send to a parent thread.
167173data ChildEvent a =
168174 ChildYield a
@@ -655,6 +661,18 @@ decrementYieldLimit sv =
655661 (if x >= 1 then x - 1 else 0, x)
656662 return $ r >= 1
657663
664+-- decrementYieldLimit returns False when the old limit is 0. This one returns
665+-- False when the old limit is 1.
666+{-# INLINE decrementYieldLimitPost #-}
667+decrementYieldLimitPost :: SVar t m a -> IO Bool
668+decrementYieldLimitPost sv =
669+ case remainingYields sv of
670+ Nothing -> return True
671+ Just ref -> do
672+ r <- atomicModifyIORefCAS ref $ \x ->
673+ (if x >= 1 then x - 1 else 0, x)
674+ return $ r > 1
675+
658676-- XXX increment is not safe when the yield limit was already 0
659677-- and therefore was not decremented. We need yield limit to be
660678-- int and negative if we want this to work.
@@ -1677,12 +1695,15 @@ getAheadSVar st f = do
16771695 (xs, _) <- readIORef q
16781696 return $ null xs
16791697
1680−getParallelSVar :: MonadIO m => IO (SVar t m a)
1681−getParallelSVar = do
1698+getParallelSVar :: MonadIO m => State t m a -> IO (SVar t m a)
1699+getParallelSVar st = do
16821700 outQ <- newIORef ([], 0)
16831701 outQMv <- newEmptyMVar
16841702 active <- newIORef 0
16851703 running <- newIORef S.empty
1704+ yl <- case getYieldLimit st of
1705+ Nothing -> return Nothing
1706+ Just x -> Just <$> newIORef x
16861707
16871708 disp <- newIORef 0
16881709 maxWrk <- newIORef 0
@@ -1696,7 +1717,7 @@ getParallelSVar = do
16961717
16971718 let sv =
16981719 SVar { outputQueue = outQ
1699− , remainingYields = Nothing
1720+ , remainingYields = yl
17001721 , maxBufferLimit = Unlimited
17011722 , maxWorkerLimit = undefined
17021723 , yieldRateInfo = Nothing
@@ -1764,8 +1785,8 @@ newAheadVar st m wloop = do
17641785 sendFirstWorker sv m
17651786
17661787{-# INLINABLE newParallelVar #-}
1767−newParallelVar :: MonadAsync m => m (SVar t m a)
1768−newParallelVar = liftIO $ getParallelSVar
1788+newParallelVar :: MonadAsync m => State t m a -> m (SVar t m a)
1789+newParallelVar st = liftIO $ getParallelSVar st
17691790
17701791-- XXX this errors out for Parallel/Ahead SVars
17711792-- | Write a stream to an 'SVar' in a non-blocking manner. The stream can then