Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(584)

Unified Diff: sdk/lib/async/stream_pipe.dart

Issue 920373003: Fix behavior when listening multiple times to a broadcast take/skip stream. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix typo Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/lib/async/stream_transformation_broadcast_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/async/stream_pipe.dart
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index ca1164dea81bb084211ee36eaff5e128bd744228..a2fc15d5e3adbfe84a89494c940f4dc7f9d96e82 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -308,20 +308,32 @@ class _HandleErrorStream<T> extends _ForwardingStream<T, T> {
class _TakeStream<T> extends _ForwardingStream<T, T> {
- int _remaining;
+ final int _count;
_TakeStream(Stream<T> source, int count)
- : this._remaining = count, super(source) {
+ : this._count = count, super(source) {
// This test is done early to avoid handling an async error
// in the _handleData method.
if (count is! int) throw new ArgumentError(count);
}
+ StreamSubscription<T> _createSubscription(
+ void onData(T data),
+ Function onError,
+ void onDone(),
+ bool cancelOnError) {
+ return new _StateStreamSubscription<T>(
+ this, onData, onError, onDone, cancelOnError, _count);
+ }
+
void _handleData(T inputEvent, _EventSink<T> sink) {
- if (_remaining > 0) {
+ _StateStreamSubscription subscription = sink;
+ int count = subscription._count;
+ if (count > 0) {
sink._add(inputEvent);
- _remaining -= 1;
- if (_remaining == 0) {
+ count -= 1;
+ subscription._count = count;
+ if (count == 0) {
// Closing also unsubscribes all subscribers, which unsubscribes
// this from source.
sink._close();
@@ -330,6 +342,26 @@ class _TakeStream<T> extends _ForwardingStream<T, T> {
}
}
+/**
+ * A [_ForwardingStreamSubscription] with one extra state field.
+ *
+ * Use by several different classes, some storing an integer, others a bool.
+ */
+class _StateStreamSubscription<T> extends _ForwardingStreamSubscription<T, T> {
+ // Raw state field. Typed access provided by getters and setters below.
+ var _sharedState;
+
+ _StateStreamSubscription(_ForwardingStream stream, void onData(T data),
+ Function onError, void onDone(),
+ bool cancelOnError, this._sharedState)
+ : super(stream, onData, onError, onDone, cancelOnError);
+
+ bool get _flag => _sharedState;
+ void set _flag(bool flag) { _sharedState = flag; }
+ int get _count => _sharedState;
+ void set _count(int count) { _sharedState = count; }
+}
+
class _TakeWhileStream<T> extends _ForwardingStream<T, T> {
final _Predicate<T> _test;
@@ -356,18 +388,29 @@ class _TakeWhileStream<T> extends _ForwardingStream<T, T> {
}
class _SkipStream<T> extends _ForwardingStream<T, T> {
- int _remaining;
+ final int _count;
_SkipStream(Stream<T> source, int count)
- : this._remaining = count, super(source) {
+ : this._count = count, super(source) {
// This test is done early to avoid handling an async error
// in the _handleData method.
if (count is! int || count < 0) throw new ArgumentError(count);
}
+ StreamSubscription<T> _createSubscription(
+ void onData(T data),
+ Function onError,
+ void onDone(),
+ bool cancelOnError) {
+ return new _StateStreamSubscription<T>(
+ this, onData, onError, onDone, cancelOnError, _count);
+ }
+
void _handleData(T inputEvent, _EventSink<T> sink) {
- if (_remaining > 0) {
- _remaining--;
+ _StateStreamSubscription subscription = sink;
+ int count = subscription._count;
+ if (count > 0) {
+ subscription._count = count - 1;
return;
}
sink._add(inputEvent);
@@ -376,13 +419,23 @@ class _SkipStream<T> extends _ForwardingStream<T, T> {
class _SkipWhileStream<T> extends _ForwardingStream<T, T> {
final _Predicate<T> _test;
- bool _hasFailed = false;
_SkipWhileStream(Stream<T> source, bool test(T value))
: this._test = test, super(source);
+ StreamSubscription<T> _createSubscription(
+ void onData(T data),
+ Function onError,
+ void onDone(),
+ bool cancelOnError) {
+ return new _StateStreamSubscription<T>(
+ this, onData, onError, onDone, cancelOnError, false);
+ }
+
void _handleData(T inputEvent, _EventSink<T> sink) {
- if (_hasFailed) {
+ _StateStreamSubscription subscription = sink;
+ bool hasFailed = subscription._flag;
+ if (hasFailed) {
sink._add(inputEvent);
return;
}
@@ -392,11 +445,11 @@ class _SkipWhileStream<T> extends _ForwardingStream<T, T> {
} catch (e, s) {
_addErrorWithReplacement(sink, e, s);
// A failure to return a boolean is considered "not matching".
- _hasFailed = true;
+ subscription._flag = true;
return;
}
if (!satisfies) {
- _hasFailed = true;
+ subscription._flag = true;
sink._add(inputEvent);
}
}
« no previous file with comments | « no previous file | tests/lib/async/stream_transformation_broadcast_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698