@@ -496,11 +496,9 @@ getStreamRate = _maxStreamRate
496setStreamLatency :: Int -> State t m a -> State t m a
496setStreamLatency :: Int -> State t m a -> State t m a
497setStreamLatency n st =
497setStreamLatency n st =
498 st { _streamLatency =
498 st { _streamLatency =
499− if n < 0
499+ if n <= 0
500 then Nothing
500 then Nothing
503− else Just (fromIntegral n)
501+ else Just (fromIntegral n)
506getStreamLatency :: State t m a -> Maybe NanoSecs
504getStreamLatency :: State t m a -> Maybe NanoSecs
@@ -513,14 +511,14 @@ getStreamLatency = _streamLatency
513cleanupSVar :: SVar t m a -> IO ()
511cleanupSVar :: SVar t m a -> IO ()
514cleanupSVar sv = do
512cleanupSVar sv = do
515 workers <- readIORef (workerThreads sv)
513 workers <- readIORef (workerThreads sv)
516− Prelude.mapM_ (\tid -> throwTo tid ThreadAbort)
514+ Prelude.mapM_ (`throwTo` ThreadAbort)
517 (S.toList workers)
515 (S.toList workers)
519cleanupSVarFromWorker :: SVar t m a -> IO ()
517cleanupSVarFromWorker :: SVar t m a -> IO ()
520cleanupSVarFromWorker sv = do
518cleanupSVarFromWorker sv = do
521 workers <- readIORef (workerThreads sv)
519 workers <- readIORef (workerThreads sv)
522 self <- myThreadId
520 self <- myThreadId
523− mapM_ (\tid -> throwTo tid ThreadAbort)
521+ mapM_ (`throwTo` ThreadAbort)
524 (S.toList workers \\ [self])
522 (S.toList workers \\ [self])
526-------------------------------------------------------------------------------
524-------------------------------------------------------------------------------
@@ -751,6 +749,21 @@ atomicModifyIORefCAS ref fn = do
751 then return result
749 then return result
752 else loop tkt (tries - 1)
750 else loop tkt (tries - 1)
752+{-# INLINE ringDoorBell #-}
753+ringDoorBell :: SVar t m a -> IO ()
756+ w <- readIORef $ needDoorBell sv
758+ -- Note: the sequence of operations is important for correctness here.
759+ -- We need to set the flag to false strictly before sending the
760+ -- outputDoorBell, otherwise the outputDoorBell may get processed too early and
761+ -- then we may set the flag to False to later making the consumer lose
762+ -- the flag, even without receiving a outputDoorBell.
763+ atomicModifyIORefCAS_ (needDoorBell sv) (const False)
764+ void $ tryPutMVar (outputDoorBell sv) ()
754------------------------------------------------------------------------------
767------------------------------------------------------------------------------
755-- Spawning threads and collecting result in streamed fashion
768-- Spawning threads and collecting result in streamed fashion
756------------------------------------------------------------------------------
769------------------------------------------------------------------------------
@@ -770,7 +783,7 @@ type MonadAsync m = (MonadIO m, MonadBaseControl IO m, MonadThrow m)
770{-# INLINE rawForkIO #-}
783{-# INLINE rawForkIO #-}
771rawForkIO :: IO () -> IO ThreadId
784rawForkIO :: IO () -> IO ThreadId
772rawForkIO action = IO $ \ s ->
785rawForkIO action = IO $ \ s ->
773− case (fork# action s) of (# s1, tid #) -> (# s1, ThreadId tid #)
786+ case fork# action s of (# s1, tid #) -> (# s1, ThreadId tid #)
775{-# INLINE doFork #-}
788{-# INLINE doFork #-}
776doFork :: MonadBaseControl IO m
789doFork :: MonadBaseControl IO m
@@ -857,7 +870,7 @@ send sv msg = do
857 Unlimited -> return True
870 Unlimited -> return True
858 Limited lim -> do
871 Limited lim -> do
859 active <- readIORef (workerCount sv)
872 active <- readIORef (workerCount sv)
860− return $ len < ((fromIntegral lim) - active)
873+ return $ len < (fromIntegral lim - active)
862workerCollectLatency :: WorkerInfo -> IO (Maybe (Count, NanoSecs))
875workerCollectLatency :: WorkerInfo -> IO (Maybe (Count, NanoSecs))
863workerCollectLatency winfo = do
876workerCollectLatency winfo = do
@@ -865,7 +878,7 @@ workerCollectLatency winfo = do
865 cnt1 <- readIORef (workerYieldCount winfo)
878 cnt1 <- readIORef (workerYieldCount winfo)
866 let cnt = cnt1 - cnt0
879 let cnt = cnt1 - cnt0
868− if (cnt > 0)
881+ if cnt > 0
870 t1 <- getTime Monotonic
883 t1 <- getTime Monotonic
871 let period = fromInteger $ toNanoSecs (t1 - t0)
884 let period = fromInteger $ toNanoSecs (t1 - t0)
@@ -919,7 +932,7 @@ checkRatePeriodic :: SVar t m a
919checkRatePeriodic sv yinfo winfo ycnt = do
932checkRatePeriodic sv yinfo winfo ycnt = do
920 i <- readIORef (workerPollingInterval yinfo)
933 i <- readIORef (workerPollingInterval yinfo)
921 -- XXX use generation count to check if the interval has been updated
934 -- XXX use generation count to check if the interval has been updated
922− if (i /= 0 && (ycnt `mod` i) == 0)
935+ if i /= 0 && (ycnt `mod` i) == 0
924 workerUpdateLatency yinfo winfo
937 workerUpdateLatency yinfo winfo
925 -- XXX not required for parallel streams
938 -- XXX not required for parallel streams
@@ -961,12 +974,11 @@ workerStopUpdate winfo info = do
961sendStop :: SVar t m a -> Maybe WorkerInfo -> IO ()
974sendStop :: SVar t m a -> Maybe WorkerInfo -> IO ()
962sendStop sv mwinfo = do
975sendStop sv mwinfo = do
963 atomicModifyIORefCAS_ (workerCount sv) $ \n -> n - 1
976 atomicModifyIORefCAS_ (workerCount sv) $ \n -> n - 1
966− case yieldRateInfo sv of
977+ case (mwinfo, yieldRateInfo sv) of
967− Nothing -> return ()
978+ (Just winfo, Just info) ->
968− Just info -> workerStopUpdate winfo info
979+ workerStopUpdate winfo info
969− Nothing -> return ()
981+ return ()
970 myThreadId >>= \tid -> void $ send sv (ChildStop tid Nothing)
982 myThreadId >>= \tid -> void $ send sv (ChildStop tid Nothing)
972-------------------------------------------------------------------------------
984-------------------------------------------------------------------------------
@@ -981,16 +993,7 @@ sendStop sv mwinfo = do
981enqueueLIFO :: SVar t m a -> IORef [t m a] -> t m a -> IO ()
993enqueueLIFO :: SVar t m a -> IORef [t m a] -> t m a -> IO ()
982enqueueLIFO sv q m = do
994enqueueLIFO sv q m = do
983 atomicModifyIORefCAS_ q $ \ms -> m : ms
995 atomicModifyIORefCAS_ q $ \ms -> m : ms
984− storeLoadBarrier
996+ ringDoorBell sv
985− w <- readIORef $ needDoorBell sv
987− -- Note: the sequence of operations is important for correctness here.
988− -- We need to set the flag to false strictly before sending the
989− -- outputDoorBell, otherwise the outputDoorBell may get processed too early and
990− -- then we may set the flag to False to later making the consumer lose
991− -- the flag, even without receiving a outputDoorBell.
992− atomicModifyIORefCAS_ (needDoorBell sv) (const False)
993− void $ tryPutMVar (outputDoorBell sv) ()
995-------------------------------------------------------------------------------
998-------------------------------------------------------------------------------
@@ -1004,16 +1007,7 @@ enqueueLIFO sv q m = do
1004enqueueFIFO :: SVar t m a -> LinkedQueue (t m a) -> t m a -> IO ()
1007enqueueFIFO :: SVar t m a -> LinkedQueue (t m a) -> t m a -> IO ()
1005enqueueFIFO sv q m = do
1008enqueueFIFO sv q m = do
1006 pushL q m
1009 pushL q m
1007− storeLoadBarrier
1010+ ringDoorBell sv
1008− w <- readIORef $ needDoorBell sv
1010− -- Note: the sequence of operations is important for correctness here.
1011− -- We need to set the flag to false strictly before sending the
1012− -- outputDoorBell, otherwise the outputDoorBell may get processed too early and
1013− -- then we may set the flag to False to later making the consumer lose
1014− -- the flag, even without receiving a outputDoorBell.
1015− atomicModifyIORefCAS_ (needDoorBell sv) (const False)
1016− void $ tryPutMVar (outputDoorBell sv) ()
1018-------------------------------------------------------------------------------
1012-------------------------------------------------------------------------------
@@ -1085,16 +1079,7 @@ enqueueAhead sv q m = do
1085 atomicModifyIORefCAS_ q $ \ case
1079 atomicModifyIORefCAS_ q $ \ case
1086 ([], n) -> ([m], n + 1) -- increment sequence
1080 ([], n) -> ([m], n + 1) -- increment sequence
1087 _ -> error "not empty"
1081 _ -> error "not empty"
1088− storeLoadBarrier
1082+ ringDoorBell sv
1089− w <- readIORef $ needDoorBell sv
1091− -- Note: the sequence of operations is important for correctness here.
1092− -- We need to set the flag to false strictly before sending the
1093− -- outputDoorBell, otherwise the outputDoorBell may get processed too early and
1094− -- then we may set the flag to False to later making the consumer lose
1095− -- the flag, even without receiving a outputDoorBell.
1096− atomicModifyIORefCAS_ (needDoorBell sv) (const False)
1097− void $ tryPutMVar (outputDoorBell sv) ()
1099-- enqueue without incrementing the sequence number
1084-- enqueue without incrementing the sequence number
1100{-# INLINE reEnqueueAhead #-}
1085{-# INLINE reEnqueueAhead #-}
@@ -1103,11 +1088,7 @@ reEnqueueAhead sv q m = do
1103 atomicModifyIORefCAS_ q $ \ case
1088 atomicModifyIORefCAS_ q $ \ case
1104 ([], n) -> ([m], n) -- DO NOT increment sequence
1089 ([], n) -> ([m], n) -- DO NOT increment sequence
1105 _ -> error "not empty"
1090 _ -> error "not empty"
1106− storeLoadBarrier
1091+ ringDoorBell sv
1107− w <- readIORef $ needDoorBell sv
1109− atomicModifyIORefCAS_ (needDoorBell sv) (const False)
1110− void $ tryPutMVar (outputDoorBell sv) ()
1112-- Normally the thread that has the token should never go away. The token gets
1093-- Normally the thread that has the token should never go away. The token gets
1113-- handed over to another thread, but someone or the other has the token at any
1094-- handed over to another thread, but someone or the other has the token at any
@@ -1138,7 +1119,7 @@ queueEmptyAhead q = liftIO $ do
1138{-# INLINE dequeueAhead #-}
1119{-# INLINE dequeueAhead #-}
1139dequeueAhead :: MonadIO m
1120dequeueAhead :: MonadIO m
1140 => IORef ([t m a], Int) -> m (Maybe (t m a, Int))
1121 => IORef ([t m a], Int) -> m (Maybe (t m a, Int))
1141−dequeueAhead q = liftIO $ do
1122+dequeueAhead q = liftIO $
1142 atomicModifyIORefCAS q $ \case
1123 atomicModifyIORefCAS q $ \case
1143 ([], n) -> (([], n), Nothing)
1124 ([], n) -> (([], n), Nothing)
1144 (x : [], n) -> (([], n), Just (x, n))
1125 (x : [], n) -> (([], n), Just (x, n))
@@ -1235,7 +1216,7 @@ addThread sv tid =
1235{-# INLINE delThread #-}
1216{-# INLINE delThread #-}
1236delThread :: MonadIO m => SVar t m a -> ThreadId -> m ()
1217delThread :: MonadIO m => SVar t m a -> ThreadId -> m ()
1237delThread sv tid =
1218delThread sv tid =
1238− liftIO $ modifyIORef (workerThreads sv) $ (\s -> S.delete tid s)
1219+ liftIO $ modifyIORef (workerThreads sv) (S.delete tid)
1240-- If present then delete else add. This takes care of out of order add and
1221-- If present then delete else add. This takes care of out of order add and
1241-- delete i.e. a delete arriving before we even added a thread.
1222-- delete i.e. a delete arriving before we even added a thread.
@@ -1245,14 +1226,13 @@ delThread sv tid =
1245modifyThread :: MonadIO m => SVar t m a -> ThreadId -> m ()
1226modifyThread :: MonadIO m => SVar t m a -> ThreadId -> m ()
1246modifyThread sv tid = do
1227modifyThread sv tid = do
1247 changed <- liftIO $ atomicModifyIORefCAS (workerThreads sv) $ \old ->
1228 changed <- liftIO $ atomicModifyIORefCAS (workerThreads sv) $ \old ->
1248− if (S.member tid old)
1229+ if S.member tid old
1249− then let new = (S.delete tid old) in (new, new)
1230+ then let new = S.delete tid old in (new, new)
1250− else let new = (S.insert tid old) in (new, old)
1231+ else let new = S.insert tid old in (new, old)
1251− if null changed
1232+ when (null changed) $
1252− then liftIO $ do
1233+ liftIO $ do
1253− writeBarrier
1234+ writeBarrier
1254− void $ tryPutMVar (outputDoorBell sv) ()
1235+ void $ tryPutMVar (outputDoorBell sv) ()
1257-- | This is safe even if we are adding more threads concurrently because if
1237-- | This is safe even if we are adding more threads concurrently because if
1258-- a child thread is adding another thread then anyway 'workerThreads' will
1238-- a child thread is adding another thread then anyway 'workerThreads' will
@@ -1292,7 +1272,7 @@ pushWorker yieldMax sv = do
1292 cntRef <- newIORef 0
1272 cntRef <- newIORef 0
1293 t <- getTime Monotonic
1273 t <- getTime Monotonic
1294 lat <- newIORef (0, t)
1274 lat <- newIORef (0, t)
1295− return $ Just $ WorkerInfo
1275+ return $ Just WorkerInfo
1296 { workerYieldMax = yieldMax
1276 { workerYieldMax = yieldMax
1297 , workerYieldCount = cntRef
1277 , workerYieldCount = cntRef
1298 , workerLatencyStart = lat
1278 , workerLatencyStart = lat
@@ -1309,10 +1289,11 @@ pushWorker yieldMax sv = do
1309-- using a CAS based modification.
1289-- using a CAS based modification.
1310{-# NOINLINE pushWorkerPar #-}
1290{-# NOINLINE pushWorkerPar #-}
1311pushWorkerPar :: MonadAsync m => SVar t m a -> (Maybe WorkerInfo -> m ()) -> m ()
1291pushWorkerPar :: MonadAsync m => SVar t m a -> (Maybe WorkerInfo -> m ()) -> m ()
1312−pushWorkerPar sv wloop = do
1292+pushWorkerPar sv wloop =
1313 -- We do not use workerCount in case of ParallelVar but still there is no
1293 -- We do not use workerCount in case of ParallelVar but still there is no
1314 -- harm in maintaining it correctly.
1294 -- harm in maintaining it correctly.
1315#ifdef DIAGNOSTICS
1295#ifdef DIAGNOSTICS
1316 liftIO $ atomicModifyIORefCAS_ (workerCount sv) $ \n -> n + 1
1297 liftIO $ atomicModifyIORefCAS_ (workerCount sv) $ \n -> n + 1
1317 recordMaxWorkers sv
1298 recordMaxWorkers sv
1318 -- This allocation matters when significant number of workers are being
1299 -- This allocation matters when significant number of workers are being
@@ -1347,14 +1328,14 @@ dispatchWorker yieldCount sv = do
1347 -- Note, "done" may not mean that the work is actually finished if there
1328 -- Note, "done" may not mean that the work is actually finished if there
1348 -- are workers active, because there may be a worker which has not yet
1329 -- are workers active, because there may be a worker which has not yet
1349 -- queued the leftover work.
1330 -- queued the leftover work.
1350− if (not done)
1331+ if not done
1352 qDone <- liftIO $ isQueueDone sv
1333 qDone <- liftIO $ isQueueDone sv
1353 -- Note that the worker count is only decremented during event
1334 -- Note that the worker count is only decremented during event
1354 -- processing in fromStreamVar and therefore it is safe to read and
1335 -- processing in fromStreamVar and therefore it is safe to read and
1355 -- use it without a lock.
1336 -- use it without a lock.
1356 active <- liftIO $ readIORef $ workerCount sv
1337 active <- liftIO $ readIORef $ workerCount sv
1357− if (not qDone)
1338+ if not qDone
1359 -- Note that we may deadlock if the previous workers (tasks in the
1340 -- Note that we may deadlock if the previous workers (tasks in the
1360 -- stream) wait/depend on the future workers (tasks in the stream)
1341 -- stream) wait/depend on the future workers (tasks in the stream)
@@ -1408,7 +1389,7 @@ rateRecoveryTime :: NanoSecs
1408rateRecoveryTime = 1000000
1389rateRecoveryTime = 1000000
1410nanoToMicroSecs :: NanoSecs -> Int
1391nanoToMicroSecs :: NanoSecs -> Int
1411−nanoToMicroSecs s = (fromIntegral s) `div` 1000
1392+nanoToMicroSecs s = fromIntegral s `div` 1000
1413-- We either block, or send one worker with limited yield count or one or more
1394-- We either block, or send one worker with limited yield count or one or more
1414-- workers with unlimited yield count.
1395-- workers with unlimited yield count.
@@ -1493,7 +1474,7 @@ estimateWorkers workerLimit svarYields gainLossYields
1493 in assert (sleepTime >= 0) $
1474 in assert (sleepTime >= 0) $
1494 -- if s is less than 0 it means our maxSleepTime is less
1475 -- if s is less than 0 it means our maxSleepTime is less
1495 -- than the worker latency.
1476 -- than the worker latency.
1496− if (s > 0) then BlockWait s else ManyWorkers 1 (Count 0)
1477+ if s > 0 then BlockWait s else ManyWorkers 1 (Count 0)
1498 withLimit n =
1479 withLimit n =
1499 case workerLimit of
1480 case workerLimit of
@@ -1519,7 +1500,7 @@ getWorkerLatency yinfo = do
1519 pendingTime = colTime + time
1500 pendingTime = colTime + time
1521 if pendingCount > 0
1502 if pendingCount > 0
1522− then let lat = pendingTime `div` (fromIntegral pendingCount)
1503+ then let lat = pendingTime `div` fromIntegral pendingCount
1523 -- XXX Give more weight to new?
1504 -- XXX Give more weight to new?
1524 in (lat + prev) `div` 2
1505 in (lat + prev) `div` 2
1525 else prev
1506 else prev
@@ -1583,9 +1564,9 @@ collectLatency _ss yinfo = do
1583 lcount' = lcount + pendingCount
1564 lcount' = lcount + pendingCount
1584 tripleWith lat = (lcount', ltime, lat)
1565 tripleWith lat = (lcount', ltime, lat)
1586− if (pendingCount > 0)
1567+ if pendingCount > 0
1588− let new = pendingTime `div` (fromIntegral pendingCount)
1569+ let new = pendingTime `div` fromIntegral pendingCount
1589#ifdef DIAGNOSTICS
1570#ifdef DIAGNOSTICS
1590 minLat <- readIORef (minWorkerLatency _ss)
1571 minLat <- readIORef (minWorkerLatency _ss)
1591 when (new < minLat || minLat == 0) $
1572 when (new < minLat || minLat == 0) $
@@ -1599,7 +1580,7 @@ collectLatency _ss yinfo = do
1599 -- return the previous latency derived from the previous batch.
1580 -- return the previous latency derived from the previous batch.
1600 if (pendingCount > fromIntegral magicMaxBuffer)
1581 if (pendingCount > fromIntegral magicMaxBuffer)
1601 || (pendingTime > minThreadDelay)
1582 || (pendingTime > minThreadDelay)
1602− || (let r = (fromIntegral new) / (fromIntegral prev) :: Double
1583+ || (let r = fromIntegral new / fromIntegral prev :: Double
1603 in prev > 0 && (r > 2 || r < 0.5))
1584 in prev > 0 && (r > 2 || r < 0.5))
1604 || (prev == 0)
1585 || (prev == 0)
@@ -1698,18 +1679,17 @@ dispatchWorkerPaced sv = do
1698 liftIO $ writeIORef periodRef period
1679 liftIO $ writeIORef periodRef period
1700 cnt <- liftIO $ readIORef $ workerCount sv
1681 cnt <- liftIO $ readIORef $ workerCount sv
1701− if (cnt < netWorkers)
1682+ if cnt < netWorkers
1703 let total = netWorkers - cnt
1684 let total = netWorkers - cnt
1704 batch = max 1 $ fromIntegral $
1685 batch = max 1 $ fromIntegral $
1705 minThreadDelay `div` targetLat
1686 minThreadDelay `div` targetLat
1706− r <- dispatchN (min total batch)
1707 -- XXX stagger the workers over a period?
1687 -- XXX stagger the workers over a period?
1708 -- XXX cannot sleep, as that would mean we cannot process the
1688 -- XXX cannot sleep, as that would mean we cannot process the
1709 -- outputs. need to try a different mechanism to stagger.
1689 -- outputs. need to try a different mechanism to stagger.
1710 -- when (total > batch) $
1690 -- when (total > batch) $
1711 -- liftIO $ threadDelay $ nanoToMicroSecs minThreadDelay
1691 -- liftIO $ threadDelay $ nanoToMicroSecs minThreadDelay
1712− return r
1692+ dispatchN (min total batch)
1713 else return False
1693 else return False
@@ -1723,7 +1703,7 @@ dispatchWorkerPaced sv = do
1723 else yields + buf
1703 else yields + buf
1724 liftIO $ modifyIORef (svarGainedLostYields yinfo) (+ delta)
1704 liftIO $ modifyIORef (svarGainedLostYields yinfo) (+ delta)
1726− dispatchN n = do
1706+ dispatchN n =
1727 if n == 0
1707 if n == 0
1728 then return True
1708 then return True
@@ -1736,12 +1716,13 @@ sendWorkerDelayPaced :: SVar t m a -> IO ()
1736sendWorkerDelayPaced _ = return ()
1716sendWorkerDelayPaced _ = return ()
1738sendWorkerDelay :: SVar t m a -> IO ()
1718sendWorkerDelay :: SVar t m a -> IO ()
1739−sendWorkerDelay _sv = do
1719+sendWorkerDelay _sv =
1740 -- XXX we need a better way to handle this than hardcoded delays. The
1720 -- XXX we need a better way to handle this than hardcoded delays. The
1741 -- delays may be different for different systems.
1721 -- delays may be different for different systems.
1742 -- If there is a usecase where this is required we can create a combinator
1722 -- If there is a usecase where this is required we can create a combinator
1743 -- to set it as a config in the state.
1723 -- to set it as a config in the state.
1745 ncpu <- getNumCapabilities
1726 ncpu <- getNumCapabilities
1746 if ncpu <= 1
1727 if ncpu <= 1
@@ -1816,7 +1797,7 @@ sendWorkerWait delay dispatch sv = do
1816 -- doorbell on the next enqueue.
1797 -- doorbell on the next enqueue.
1818 liftIO $ atomicModifyIORefCAS_ (needDoorBell sv) $ const True
1799 liftIO $ atomicModifyIORefCAS_ (needDoorBell sv) $ const True
1819− liftIO $ storeLoadBarrier
1800+ liftIO storeLoadBarrier
1820 canDoMore <- dispatch sv
1801 canDoMore <- dispatch sv
1822 -- XXX test for the case when we miss sending a worker when the worker
1803 -- XXX test for the case when we miss sending a worker when the worker
@@ -1865,12 +1846,12 @@ readOutputQBounded sv = do
1865 cnt <- liftIO $ readIORef $ workerCount sv
1846 cnt <- liftIO $ readIORef $ workerCount sv
1866 when (cnt <= 0) $ do
1847 when (cnt <= 0) $ do
1867 done <- liftIO $ isWorkDone sv
1848 done <- liftIO $ isWorkDone sv
1868− when (not done) $ pushWorker 0 sv
1849+ when (not done) (pushWorker 0 sv)
1870 {-# INLINE blockingRead #-}
1851 {-# INLINE blockingRead #-}
1871 blockingRead = do
1852 blockingRead = do
1872 sendWorkerWait sendWorkerDelay (dispatchWorker 0) sv
1853 sendWorkerWait sendWorkerDelay (dispatchWorker 0) sv
1873− liftIO $ (readOutputQRaw sv >>= return . fst)
1854+ liftIO (fst `fmap` readOutputQRaw sv)
1875readOutputQPaced :: MonadAsync m => SVar t m a -> m [ChildEvent a]
1856readOutputQPaced :: MonadAsync m => SVar t m a -> m [ChildEvent a]
1876readOutputQPaced sv = do
1857readOutputQPaced sv = do
@@ -1888,7 +1869,7 @@ readOutputQPaced sv = do
1888 {-# INLINE blockingRead #-}
1869 {-# INLINE blockingRead #-}
1889 blockingRead = do
1870 blockingRead = do
1890 sendWorkerWait sendWorkerDelayPaced dispatchWorkerPaced sv
1871 sendWorkerWait sendWorkerDelayPaced dispatchWorkerPaced sv
1891− liftIO $ (readOutputQRaw sv >>= return . fst)
1872+ liftIO (fst `fmap` readOutputQRaw sv)
1893postProcessBounded :: MonadAsync m => SVar t m a -> m Bool
1874postProcessBounded :: MonadAsync m => SVar t m a -> m Bool
1894postProcessBounded sv = do
1875postProcessBounded sv = do
@@ -1907,7 +1888,7 @@ postProcessBounded sv = do
1907 r <- liftIO $ isWorkDone sv
1888 r <- liftIO $ isWorkDone sv
1908 -- Note that we need to guarantee a worker, therefore we cannot just
1889 -- Note that we need to guarantee a worker, therefore we cannot just
1909 -- use dispatchWorker which may or may not send a worker.
1890 -- use dispatchWorker which may or may not send a worker.
1910− when (not r) $ pushWorker 0 sv
1891+ when (not r) (pushWorker 0 sv)
1911 -- XXX do we need to dispatch many here?
1892 -- XXX do we need to dispatch many here?
1912 -- void $ dispatchWorker sv
1893 -- void $ dispatchWorker sv
1913 return r
1894 return r
@@ -2150,7 +2131,7 @@ getParallelSVar st = do
2150 case yieldRateInfo sv of
2131 case yieldRateInfo sv of
2151 Nothing -> return ()
2132 Nothing -> return ()
2152 Just yinfo -> void $ collectLatency (svarStats sv) yinfo
2133 Just yinfo -> void $ collectLatency (svarStats sv) yinfo
2153− readOutputQRaw sv >>= return . fst
2134+ fst `fmap` readOutputQRaw sv
2155sendFirstWorker :: MonadAsync m => SVar t m a -> t m a -> m (SVar t m a)
2136sendFirstWorker :: MonadAsync m => SVar t m a -> t m a -> m (SVar t m a)
2156sendFirstWorker sv m = do
2137sendFirstWorker sv m = do
@@ -2160,7 +2141,7 @@ sendFirstWorker sv m = do
2160 liftIO $ enqueue sv m
2141 liftIO $ enqueue sv m
2161 case yieldRateInfo sv of
2142 case yieldRateInfo sv of
2162 Nothing -> pushWorker 0 sv
2143 Nothing -> pushWorker 0 sv
2163− Just yinfo -> do
2144+ Just yinfo ->
2164 if svarLatencyTarget yinfo == maxBound
2145 if svarLatencyTarget yinfo == maxBound
2165 then liftIO $ threadDelay maxBound
2146 then liftIO $ threadDelay maxBound
2166 else pushWorker 1 sv
2147 else pushWorker 1 sv
@@ -2190,7 +2171,7 @@ newParallelVar st = liftIO $ getParallelSVar st
2190-- be read back from the SVar using 'fromSVar'.
2171-- be read back from the SVar using 'fromSVar'.
2191toStreamVar :: MonadAsync m => SVar t m a -> t m a -> m ()
2172toStreamVar :: MonadAsync m => SVar t m a -> t m a -> m ()
2192toStreamVar sv m = do
2173toStreamVar sv m = do
2193− liftIO $ (enqueue sv) m
2174+ liftIO $ enqueue sv m
2194 done <- allThreadsDone sv
2175 done <- allThreadsDone sv
2195 -- XXX This is safe only when called from the consumer thread or when no
2176 -- XXX This is safe only when called from the consumer thread or when no
2196 -- consumer is present. There may be a race if we are not running in the
2177 -- consumer is present. There may be a race if we are not running in the