-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MultiStreamController.isPaused
remains true
after resume()
#56915
Comments
Summary: The |
TL;DR: Because stream-controllers lie about pause. It's deliberate. In the optimal case, there is never any, or at least more than one, enqueued events. Events are delivered as soon as possible (first available microtask slot), and an event producer shouldn't produce events faster than they can be consumed. That leads to buffering, and consumers are expected to pause if they can't keep up with events. When a stream subscription is paused, the consumer has said that it can't keep up with events. That's not special to multi-stream controllers, you get the same effect using: main() {
asyncStart();
var controller = StreamController<int>();
controller.onListen = () {
Expect.isFalse(controller.isPaused);
controller.add(1);
controller.add(2);
controller.add(3);
};
theController = controller;
var stream = controller.stream;
listen(stream);
} (It's not unsurprising that they behave the same way, they all use the same code. The If you add Timer(Duration(milliseconds: 200), () {
controller.add(4);
}); after the A stream subscription has two flags internally: "isPaused" (a counter, actually) and "input-paused" which is what it reports to the controller. When the subscription user's pause is resumed, if the queue is not empty, the input-paused flag isn't cleared, the pending events are just scheduled. When the last pending event has been delivered, and the subscription isn't paused, the internal-paused flag is cleared. void resume() {
if (_isCanceled) return;
if (_isPaused) {
_decrementPauseCount();
if (!_isPaused) {
if (_hasPending && !_pending!.isEmpty) {
// Input is still paused.
_pending!.schedule(this);
} else {
assert(_mayResumeInput);
_state &= ~_STATE_INPUT_PAUSED;
if (!_inCallback) _guardCallback(_onResume);
}
}
}
} Testing a controller by filling up its pending event queue with everything during the (Also remember to close the controller.) |
Thank you for the explanation. Then, I'm going to change the test to: ...
if (v == 1) {
ss.pause(Future.delayed(Duration(milliseconds: 100)));
} else {
Expect.isTrue(theController.isPaused); // It's Ok. See https://github.com/dart-lang/sdk/issues/56915 for more details.
}
... |
That should be correct. If we ever change behavior (and we haven't so far, so we probably won't) then this test will catch it. |
The following test fails. Why?
cc @lrhn
The text was updated successfully, but these errors were encountered: