-
Notifications
You must be signed in to change notification settings - Fork 11
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
Consider to make second invocation of streamQueue.hasNext
be postponed concluding the result until the first invocation of q.next
, unless the stream is closed.
#356
Comments
It's a queue. If you interleave operations between unrelated asynchronous consumers, then it's not safe. Neither is the normal import "dart:collection";
var queue = Queue.from([1, 2, 3]);
Future<int?> fetch() async {
await something();
if (queue.isNotEmpty) {
await something();
var result = queue.removeFirst();
await something();
return result;
}
return null;
}
Future<void> something() async {}
void main() async {
// Fetch up to four values.
var values = Future.wait([fetch(), fetch(), fetch(), fetch()]);
} If you break up the We probably can change the behavior so that It's not true that the stream controller only wakes one consumer. import "dart:async";
import "package:async/async.dart";
void main() async {
var c = StreamController();
var q = StreamQueue(c.stream);
q.hasNext.then((n) {
print("1: $n");
});
q.hasNext.then((n) {
print("2: $n");
});
q.next.then((v) {
print("3: $v");
});
q.hasNext.then((n) {
print("4: $n");
});
c.add("event");
c.close();
} This prints If anything has changed, it's probably the timing of The suggestion here is to postpone a second It doesn't solve the actual problem. If someone does The request queue is still a queue. What you really need is an atomic We try not to change timing of asynchronous operations, because it always breaks some fragile code. but we have never actually promised that current scheduling and ordering of asynchronous events. Every part of the specification of asynchrony contains allows some leeway by using phrases like "in a later microtask". |
q.hasNext.then((n) {
print("4: $n");
});
|
That The class may need better documentation, but the underlying model is actually simple and predictable. |
I myself understand the behavior, but I think almost nobody can understand such behavior. |
Sorry, I mistakenly said |
Not planning any change here. That's a different class, which can also exist (or can be implemented as a wrapper around the normal |
First of all. it is very unintuitive that
await q.next
just afterawait q.hasNext
returningtrue
might fail.2nd, there is no way to safely consume events in a
StreamQueue
one by one without additional uselessList
fromawait q.take(1)
.3rd, in case of
sc = StreamController(); q = StreamQueue(sc.stream)
,sc.add(e)
awakes only one caller ofawait q.hasNext
and the succeedingawait q.next
always succeeds. It is inconsistent withq = StreamQueue(Stream.fromIterable(list))
Finally, it is a breaking chang unintentionally introduced by the reimplementation of async in SDK 2.18, I guess.
A possible solution I think is that the second
q.hasNext
should proactively enter the event loop, even if the stream already has a event.See dart-lang/sdk#50217 and #355, as well.
The text was updated successfully, but these errors were encountered: