Skip to content

Commit 4aba8e4

Browse files
committed
Fix NIOAsyncSequenceProducer watermark strategy.
# Motivation It was currently possible that the producer's delegate is getting called twice with `produceMore` even if no `yield` returned a `stopProducing`. This could happen when we expected the producer to yield elements but the consumer went below the low watermark again. Resulting in two subsequent calls. # Modification This PR stores the current demand state in the strategy which let's us avoid flipping the `hasOustandingDemand` state of the sequence. # Result Correctly, ensured the call order of `produceMore` and `stopProducing`.
1 parent 1ff5fd5 commit 4aba8e4

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

Sources/NIOCore/AsyncSequences/NIOAsyncSequenceProducerStrategies.swift

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public enum NIOAsyncSequenceProducerBackPressureStrategies {
2222
public struct HighLowWatermark: NIOAsyncSequenceProducerBackPressureStrategy {
2323
private let lowWatermark: Int
2424
private let highWatermark: Int
25+
private var hasOustandingDemand: Bool = false
2526

2627
/// Initializes a new ``NIOAsyncSequenceProducerBackPressureStrategies/HighLowWatermark``.
2728
///
@@ -36,12 +37,29 @@ public enum NIOAsyncSequenceProducerBackPressureStrategies {
3637

3738
public mutating func didYield(bufferDepth: Int) -> Bool {
3839
// We are demanding more until we reach the high watermark
39-
bufferDepth < self.highWatermark
40+
if bufferDepth < self.highWatermark {
41+
precondition(self.hasOustandingDemand)
42+
return true
43+
} else {
44+
self.hasOustandingDemand = false
45+
return false
46+
}
4047
}
4148

4249
public mutating func didConsume(bufferDepth: Int) -> Bool {
4350
// We start demanding again once we are below the low watermark
44-
bufferDepth < self.lowWatermark
51+
if bufferDepth < self.lowWatermark {
52+
if self.hasOustandingDemand {
53+
// We are below and have outstanding demand
54+
return true
55+
} else {
56+
// We are below but don't have outstanding demand but need more
57+
self.hasOustandingDemand = true
58+
return true
59+
}
60+
} else {
61+
return self.hasOustandingDemand
62+
}
4563
}
4664
}
4765
}

0 commit comments

Comments
 (0)