@@ -70,6 +70,8 @@ module Streamly.SVar
7070
7171 , queueEmptyAhead
7272 , dequeueAhead
73+
74+ , HeapDequeueResult(..)
7375 , dequeueFromHeap
7476 , dequeueFromHeapSeq
7577 , requeueOnHeapTop
@@ -366,7 +368,8 @@ data SVar t m a = SVar
366368 , svarRef :: Maybe (IORef ())
367369#ifdef DIAGNOSTICS
368370 , svarCreator :: ThreadId
369− , outputHeap :: IORef (Heap (Entry Int (AheadHeapEntry t m a)) , Int)
371+ , outputHeap :: IORef ( Heap (Entry Int (AheadHeapEntry t m a))
372+ , Maybe Int)
370373 -- Shared work queue (stream, seqNo)
371374 , aheadWorkQueue :: IORef ([t m a], Int)
372375#endif
@@ -1137,17 +1140,9 @@ dequeueAhead q = liftIO $ do
11371140 (x : [], n) -> (([], n), Just (x, n))
11381141 _ -> error "more than one item on queue"
11391142
1140−{-# INLINE dequeueFromHeap #-}
1141−dequeueFromHeap
1142− :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
1143− -> IO (Maybe (Entry Int (AheadHeapEntry t m a)))
1144−dequeueFromHeap hpVar =
1145− atomicModifyIORef hpVar $ \pair@(hp, snum) -> do
1146− let r = H.uncons hp
1147− case r of
1148− Just (ent@(Entry seqNo _ev), hp') | seqNo == snum ->
1149− ((hp', snum), Just ent)
1150− _ -> (pair, Nothing)
1143+-------------------------------------------------------------------------------
1144+-- Heap manipulation
1145+-------------------------------------------------------------------------------
11511146
11521147withIORef :: IORef a -> (a -> IO b) -> IO b
11531148withIORef ref f = readIORef ref >>= f
@@ -1156,46 +1151,72 @@ atomicModifyIORef_ :: IORef a -> (a -> a) -> IO ()
11561151atomicModifyIORef_ ref f =
11571152 atomicModifyIORef ref $ \x -> (f x, ())
11581153
1154+data HeapDequeueResult t m a =
1155+ Clearing
1156+ | Waiting Int
1157+ | Ready (Entry Int (AheadHeapEntry t m a))
1158+
1159+{-# INLINE dequeueFromHeap #-}
1160+dequeueFromHeap
1161+ :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int)
1162+ -> IO (HeapDequeueResult t m a)
1163+dequeueFromHeap hpVar =
1164+ atomicModifyIORef hpVar $ \pair@(hp, snum) ->
1165+ case snum of
1166+ Nothing -> (pair, Clearing)
1167+ Just n -> do
1168+ let r = H.uncons hp
1169+ case r of
1170+ Just (ent@(Entry seqNo _ev), hp') | seqNo == n ->
1171+ ((hp', Nothing), Ready ent)
1172+ _ -> (pair, Waiting n)
1173+
11591174{-# INLINE canDequeueFromHeap #-}
11601175canDequeueFromHeap
1161− :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
1176+ :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int)
11621177 -> IO Bool
11631178canDequeueFromHeap hpVar =
1164− withIORef hpVar $ \(hp, snum) -> do
1165− let r = H.uncons hp
1166− case r of
1167− Just ((Entry seqNo _ev), _) -> return $ seqNo == snum
1168− _ -> return False
1179+ withIORef hpVar $ \(hp, snum) ->
1180+ case snum of
1181+ Nothing -> return True
1182+ Just n -> do
1183+ let r = H.uncons hp
1184+ case r of
1185+ Just ((Entry seqNo _ev), _) -> return $ seqNo == n
1186+ _ -> return False
11691187
11701188{-# INLINE dequeueFromHeapSeq #-}
11711189dequeueFromHeapSeq
1172− :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
1190+ :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int)
11731191 -> Int
1174− -> IO (Maybe (Entry Int (AheadHeapEntry t m a)))
1175−dequeueFromHeapSeq hpVar snum =
1176− atomicModifyIORef hpVar $ \(hp, _) -> do
1177− let r = H.uncons hp
1178− case r of
1179− Just (ent@(Entry seqNo _ev), hp') | seqNo == snum ->
1180− ((hp', snum), Just ent)
1181− _ -> ((hp, snum), Nothing)
1192+ -> IO (HeapDequeueResult t m a)
1193+dequeueFromHeapSeq hpVar i =
1194+ atomicModifyIORef hpVar $ \(hp, snum) ->
1195+ case snum of
1196+ Nothing -> do
1197+ let r = H.uncons hp
1198+ case r of
1199+ Just (ent@(Entry seqNo _ev), hp') | seqNo == i ->
1200+ ((hp', Nothing), Ready ent)
1201+ _ -> ((hp, Just i), Waiting i)
1202+ Just _ -> error "dequeueFromHeapSeq: unreachable"
11821203
11831204{-# INLINE requeueOnHeapTop #-}
11841205requeueOnHeapTop
1185− :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
1206+ :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int)
11861207 -> Entry Int (AheadHeapEntry t m a)
11871208 -> Int
11881209 -> IO ()
11891210requeueOnHeapTop hpVar ent seqNo =
1190− atomicModifyIORef_ hpVar $ \(hp, _) -> (H.insert ent hp, seqNo)
1211+ atomicModifyIORef_ hpVar $ \(hp, _) -> (H.insert ent hp, Just seqNo)
11911212
11921213{-# INLINE updateHeapSeq #-}
11931214updateHeapSeq
1194− :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
1215+ :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int)
11951216 -> Int
11961217 -> IO ()
11971218updateHeapSeq hpVar seqNo =
1198− atomicModifyIORef_ hpVar $ \(hp, _) -> (hp, seqNo)
1219+ atomicModifyIORef_ hpVar $ \(hp, _) -> (hp, Just seqNo)
11991220
12001221-------------------------------------------------------------------------------
12011222-- WAhead
@@ -1958,7 +1979,7 @@ getYieldRateInfo st = do
19581979getAheadSVar :: MonadAsync m
19591980 => State t m a
19601981 -> ( IORef ([t m a], Int)
1961− -> IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
1982+ -> IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int)
19621983 -> State t m a
19631984 -> SVar t m a
19641985 -> Maybe WorkerInfo
@@ -1966,7 +1987,10 @@ getAheadSVar :: MonadAsync m
19661987 -> IO (SVar t m a)
19671988getAheadSVar st f = do
19681989 outQ <- newIORef ([], 0)
1969− outH <- newIORef (H.empty, 0)
1990+ -- the second component of the tuple is "Nothing" when heap is being
1991+ -- cleared, "Just n" when we are expecting sequence number n to arrive
1992+ -- before we can start clearing the heap.
1993+ outH <- newIORef (H.empty, Just 0)
19701994 outQMv <- newEmptyMVar
19711995 active <- newIORef 0
19721996 wfw <- newIORef False
@@ -2157,7 +2181,7 @@ newAheadVar :: MonadAsync m
21572181 => State t m a
21582182 -> t m a
21592183 -> ( IORef ([t m a], Int)
2160− -> IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
2184+ -> IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int)
21612185 -> State t m a
21622186 -> SVar t m a
21632187 -> Maybe WorkerInfo