Skip to content

Commit

Permalink
Fix NIOAsyncSequenceProducer watermark strategy.
Browse files Browse the repository at this point in the history
# 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`.
  • Loading branch information
FranzBusch committed Oct 28, 2024
1 parent 1ff5fd5 commit 4aba8e4
Showing 1 changed file with 20 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public enum NIOAsyncSequenceProducerBackPressureStrategies {
public struct HighLowWatermark: NIOAsyncSequenceProducerBackPressureStrategy {
private let lowWatermark: Int
private let highWatermark: Int
private var hasOustandingDemand: Bool = false

/// Initializes a new ``NIOAsyncSequenceProducerBackPressureStrategies/HighLowWatermark``.
///
Expand All @@ -36,12 +37,29 @@ public enum NIOAsyncSequenceProducerBackPressureStrategies {

public mutating func didYield(bufferDepth: Int) -> Bool {
// We are demanding more until we reach the high watermark
bufferDepth < self.highWatermark
if bufferDepth < self.highWatermark {
precondition(self.hasOustandingDemand)
return true
} else {
self.hasOustandingDemand = false
return false
}
}

public mutating func didConsume(bufferDepth: Int) -> Bool {
// We start demanding again once we are below the low watermark
bufferDepth < self.lowWatermark
if bufferDepth < self.lowWatermark {
if self.hasOustandingDemand {
// We are below and have outstanding demand
return true
} else {
// We are below but don't have outstanding demand but need more
self.hasOustandingDemand = true
return true
}
} else {
return self.hasOustandingDemand
}
}
}
}

0 comments on commit 4aba8e4

Please sign in to comment.