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

Side by Side Diff: sdk/lib/async/stream_impl.dart

Issue 357283003: Fix listeners being added to subscription after onListen was called. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/async/stream_controller.dart ('k') | sdk/lib/async/stream_pipe.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.async; 5 part of dart.async;
6 6
7 /** Abstract and private interface for a place to put events. */ 7 /** Abstract and private interface for a place to put events. */
8 abstract class _EventSink<T> { 8 abstract class _EventSink<T> {
9 void _add(T data); 9 void _add(T data);
10 void _addError(Object error, StackTrace stackTrace); 10 void _addError(Object error, StackTrace stackTrace);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 /** The future [_onCancel] may return. */ 101 /** The future [_onCancel] may return. */
102 Future _cancelFuture; 102 Future _cancelFuture;
103 103
104 /** 104 /**
105 * Queue of pending events. 105 * Queue of pending events.
106 * 106 *
107 * Is created when necessary, or set in constructor for preconfigured events. 107 * Is created when necessary, or set in constructor for preconfigured events.
108 */ 108 */
109 _PendingEvents _pending; 109 _PendingEvents _pending;
110 110
111 _BufferingStreamSubscription(bool cancelOnError) 111 _BufferingStreamSubscription(void onData(T data),
112 : _state = (cancelOnError ? _STATE_CANCEL_ON_ERROR : 0); 112 Function onError,
113 void onDone(),
114 bool cancelOnError)
115 : _state = (cancelOnError ? _STATE_CANCEL_ON_ERROR : 0) {
116 this.onData(onData);
117 this.onError(onError);
118 this.onDone(onDone);
119 }
113 120
114 /** 121 /**
115 * Sets the subscription's pending events object. 122 * Sets the subscription's pending events object.
116 * 123 *
117 * This can only be done once. The pending events object is used for the 124 * This can only be done once. The pending events object is used for the
118 * rest of the subscription's life cycle. 125 * rest of the subscription's life cycle.
119 */ 126 */
120 void _setPendingEvents(_PendingEvents pendingEvents) { 127 void _setPendingEvents(_PendingEvents pendingEvents) {
121 assert(_pending == null); 128 assert(_pending == null);
122 if (pendingEvents == null) return; 129 if (pendingEvents == null) return;
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 // ------------------------------------------------------------------- 466 // -------------------------------------------------------------------
460 abstract class _StreamImpl<T> extends Stream<T> { 467 abstract class _StreamImpl<T> extends Stream<T> {
461 // ------------------------------------------------------------------ 468 // ------------------------------------------------------------------
462 // Stream interface. 469 // Stream interface.
463 470
464 StreamSubscription<T> listen(void onData(T data), 471 StreamSubscription<T> listen(void onData(T data),
465 { Function onError, 472 { Function onError,
466 void onDone(), 473 void onDone(),
467 bool cancelOnError }) { 474 bool cancelOnError }) {
468 cancelOnError = identical(true, cancelOnError); 475 cancelOnError = identical(true, cancelOnError);
469 StreamSubscription subscription = _createSubscription(cancelOnError); 476 StreamSubscription subscription =
470 subscription.onData(onData); 477 _createSubscription(onData, onError, onDone, cancelOnError);
471 subscription.onError(onError);
472 subscription.onDone(onDone);
473 _onListen(subscription); 478 _onListen(subscription);
474 return subscription; 479 return subscription;
475 } 480 }
476 481
477 // ------------------------------------------------------------------- 482 // -------------------------------------------------------------------
478 /** Create a subscription object. Called by [subcribe]. */ 483 /** Create a subscription object. Called by [subcribe]. */
479 _BufferingStreamSubscription<T> _createSubscription(bool cancelOnError) { 484 _BufferingStreamSubscription<T> _createSubscription(
480 return new _BufferingStreamSubscription<T>(cancelOnError); 485 void onData(T data),
486 Function onError,
487 void onDone(),
488 bool cancelOnError) {
489 return new _BufferingStreamSubscription<T>(onData, onError, onDone,
490 cancelOnError);
481 } 491 }
482 492
483 /** Hook called when the subscription has been created. */ 493 /** Hook called when the subscription has been created. */
484 void _onListen(StreamSubscription subscription) {} 494 void _onListen(StreamSubscription subscription) {}
485 } 495 }
486 496
487 typedef _PendingEvents _EventGenerator(); 497 typedef _PendingEvents _EventGenerator();
488 498
489 /** Stream that generates its own events. */ 499 /** Stream that generates its own events. */
490 class _GeneratedStreamImpl<T> extends _StreamImpl<T> { 500 class _GeneratedStreamImpl<T> extends _StreamImpl<T> {
491 final _EventGenerator _pending; 501 final _EventGenerator _pending;
492 bool _isUsed = false; 502 bool _isUsed = false;
493 /** 503 /**
494 * Initializes the stream to have only the events provided by a 504 * Initializes the stream to have only the events provided by a
495 * [_PendingEvents]. 505 * [_PendingEvents].
496 * 506 *
497 * A new [_PendingEvents] must be generated for each listen. 507 * A new [_PendingEvents] must be generated for each listen.
498 */ 508 */
499 _GeneratedStreamImpl(this._pending); 509 _GeneratedStreamImpl(this._pending);
500 510
501 StreamSubscription _createSubscription(bool cancelOnError) { 511 StreamSubscription _createSubscription(
512 void onData(T data),
513 Function onError,
514 void onDone(),
515 bool cancelOnError) {
502 if (_isUsed) throw new StateError("Stream has already been listened to."); 516 if (_isUsed) throw new StateError("Stream has already been listened to.");
503 _isUsed = true; 517 _isUsed = true;
504 _BufferingStreamSubscription<T> subscription = 518 return new _BufferingStreamSubscription(
505 new _BufferingStreamSubscription(cancelOnError); 519 onData, onError, onDone, cancelOnError).._setPendingEvents(_pending());
506 subscription._setPendingEvents(_pending());
507 return subscription;
508 } 520 }
509 } 521 }
510 522
511 523
512 /** Pending events object that gets its events from an [Iterable]. */ 524 /** Pending events object that gets its events from an [Iterable]. */
513 class _IterablePendingEvents<T> extends _PendingEvents { 525 class _IterablePendingEvents<T> extends _PendingEvents {
514 // The iterator providing data for data events. 526 // The iterator providing data for data events.
515 // Set to null when iteration has completed. 527 // Set to null when iteration has completed.
516 Iterator<T> _iterator; 528 Iterator<T> _iterator;
517 529
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 // Return a dummy subscription backed by nothing, since 829 // Return a dummy subscription backed by nothing, since
818 // it will only ever send one done event. 830 // it will only ever send one done event.
819 return new _DoneStreamSubscription<T>(onDone); 831 return new _DoneStreamSubscription<T>(onDone);
820 } 832 }
821 if (_subscription == null) { 833 if (_subscription == null) {
822 _subscription = _source.listen(_controller.add, 834 _subscription = _source.listen(_controller.add,
823 onError: _controller.addError, 835 onError: _controller.addError,
824 onDone: _controller.close); 836 onDone: _controller.close);
825 } 837 }
826 cancelOnError = identical(true, cancelOnError); 838 cancelOnError = identical(true, cancelOnError);
827 StreamSubscription<T> result = _controller._subscribe(cancelOnError); 839 return _controller._subscribe(onData, onError, onDone, cancelOnError);
828 result.onData(onData);
829 result.onError(onError);
830 result.onDone(onDone);
831 return result;
832 } 840 }
833 841
834 void _onCancel() { 842 void _onCancel() {
835 bool shutdown = (_controller == null) || _controller.isClosed; 843 bool shutdown = (_controller == null) || _controller.isClosed;
836 if (_onCancelHandler != null) { 844 if (_onCancelHandler != null) {
837 _zone.runUnary(_onCancelHandler, new _BroadcastSubscriptionWrapper(this)); 845 _zone.runUnary(_onCancelHandler, new _BroadcastSubscriptionWrapper(this));
838 } 846 }
839 if (shutdown) { 847 if (shutdown) {
840 if (_subscription != null) { 848 if (_subscription != null) {
841 _subscription.cancel(); 849 _subscription.cancel();
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 _Future<bool> hasNext = _futureOrPrefetch; 1075 _Future<bool> hasNext = _futureOrPrefetch;
1068 _clear(); 1076 _clear();
1069 hasNext._complete(false); 1077 hasNext._complete(false);
1070 return; 1078 return;
1071 } 1079 }
1072 _subscription.pause(); 1080 _subscription.pause();
1073 _futureOrPrefetch = null; 1081 _futureOrPrefetch = null;
1074 _state = _STATE_EXTRA_DONE; 1082 _state = _STATE_EXTRA_DONE;
1075 } 1083 }
1076 } 1084 }
OLDNEW
« no previous file with comments | « sdk/lib/async/stream_controller.dart ('k') | sdk/lib/async/stream_pipe.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698