Chromium Code Reviews| OLD | NEW |
|---|---|
| 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); | 10 void _addError(Object error); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 static const int _STATE_CANCELED = 8; | 73 static const int _STATE_CANCELED = 8; |
| 74 static const int _STATE_IN_CALLBACK = 16; | 74 static const int _STATE_IN_CALLBACK = 16; |
| 75 static const int _STATE_HAS_PENDING = 32; | 75 static const int _STATE_HAS_PENDING = 32; |
| 76 static const int _STATE_PAUSE_COUNT = 64; | 76 static const int _STATE_PAUSE_COUNT = 64; |
| 77 static const int _STATE_PAUSE_COUNT_SHIFT = 6; | 77 static const int _STATE_PAUSE_COUNT_SHIFT = 6; |
| 78 | 78 |
| 79 /* Event handlers provided in constructor. */ | 79 /* Event handlers provided in constructor. */ |
| 80 _DataHandler<T> _onData; | 80 _DataHandler<T> _onData; |
| 81 _ErrorHandler _onError; | 81 _ErrorHandler _onError; |
| 82 _DoneHandler _onDone; | 82 _DoneHandler _onDone; |
| 83 final _Zone _zone = _Zone.current; | 83 final Zone _zone = Zone.current; |
| 84 | 84 |
| 85 /** Bit vector based on state-constants above. */ | 85 /** Bit vector based on state-constants above. */ |
| 86 int _state; | 86 int _state; |
| 87 | 87 |
| 88 /** | 88 /** |
| 89 * Queue of pending events. | 89 * Queue of pending events. |
| 90 * | 90 * |
| 91 * Is created when necessary, or set in constructor for preconfigured events. | 91 * Is created when necessary, or set in constructor for preconfigured events. |
| 92 */ | 92 */ |
| 93 _PendingEvents _pending; | 93 _PendingEvents _pending; |
| 94 | 94 |
| 95 _BufferingStreamSubscription(this._onData, | 95 _BufferingStreamSubscription(void onData(T data), |
| 96 this._onError, | 96 void onError(error), |
| 97 this._onDone, | 97 void onDone(), |
| 98 bool cancelOnError) | 98 bool cancelOnError) |
| 99 : _state = (cancelOnError ? _STATE_CANCEL_ON_ERROR : 0) { | 99 : _onData = Zone.current.registerCallback1(onData), |
| 100 _onError = Zone.current.registerCallback1(onError), | |
| 101 _onDone = Zone.current.registerCallback(onDone), | |
| 102 _state = (cancelOnError ? _STATE_CANCEL_ON_ERROR : 0) { | |
| 100 assert(_onData != null); | 103 assert(_onData != null); |
| 101 assert(_onError != null); | 104 assert(_onError != null); |
| 102 assert(_onDone != null); | 105 assert(_onDone != null); |
| 103 _zone.expectCallback(); | |
| 104 } | 106 } |
| 105 | 107 |
| 106 /** | 108 /** |
| 107 * Sets the subscription's pending events object. | 109 * Sets the subscription's pending events object. |
| 108 * | 110 * |
| 109 * This can only be done once. The pending events object is used for the | 111 * This can only be done once. The pending events object is used for the |
| 110 * rest of the subscription's life cycle. | 112 * rest of the subscription's life cycle. |
| 111 */ | 113 */ |
| 112 void _setPendingEvents(_PendingEvents pendingEvents) { | 114 void _setPendingEvents(_PendingEvents pendingEvents) { |
| 113 assert(_pending == null); | 115 assert(_pending == null); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 bool get _isPaused => _state >= _STATE_PAUSE_COUNT; | 214 bool get _isPaused => _state >= _STATE_PAUSE_COUNT; |
| 213 bool get _canFire => _state < _STATE_IN_CALLBACK; | 215 bool get _canFire => _state < _STATE_IN_CALLBACK; |
| 214 bool get _mayResumeInput => | 216 bool get _mayResumeInput => |
| 215 !_isPaused && (_pending == null || _pending.isEmpty); | 217 !_isPaused && (_pending == null || _pending.isEmpty); |
| 216 bool get _cancelOnError => (_state & _STATE_CANCEL_ON_ERROR) != 0; | 218 bool get _cancelOnError => (_state & _STATE_CANCEL_ON_ERROR) != 0; |
| 217 | 219 |
| 218 bool get isPaused => _isPaused; | 220 bool get isPaused => _isPaused; |
| 219 | 221 |
| 220 void _cancel() { | 222 void _cancel() { |
| 221 _state |= _STATE_CANCELED; | 223 _state |= _STATE_CANCELED; |
| 222 _zone.cancelCallbackExpectation(); | |
| 223 if (_hasPending) { | 224 if (_hasPending) { |
| 224 _pending.cancelSchedule(); | 225 _pending.cancelSchedule(); |
| 225 } | 226 } |
| 226 } | 227 } |
| 227 | 228 |
| 228 /** | 229 /** |
| 229 * Increment the pause count. | 230 * Increment the pause count. |
| 230 * | 231 * |
| 231 * Also marks input as paused. | 232 * Also marks input as paused. |
| 232 */ | 233 */ |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 } | 316 } |
| 316 | 317 |
| 317 /* _EventDispatch interface. */ | 318 /* _EventDispatch interface. */ |
| 318 | 319 |
| 319 void _sendData(T data) { | 320 void _sendData(T data) { |
| 320 assert(!_isCanceled); | 321 assert(!_isCanceled); |
| 321 assert(!_isPaused); | 322 assert(!_isPaused); |
| 322 assert(!_inCallback); | 323 assert(!_inCallback); |
| 323 bool wasInputPaused = _isInputPaused; | 324 bool wasInputPaused = _isInputPaused; |
| 324 _state |= _STATE_IN_CALLBACK; | 325 _state |= _STATE_IN_CALLBACK; |
| 325 _zone.executePeriodicCallbackGuarded(() => _onData(data)); | 326 _zone.runGuarded1(_onData, data); |
|
Lasse Reichstein Nielsen
2013/09/23 14:24:12
Is that runGuarded*digit one*? It's very hard to r
floitsch
2013/09/23 17:12:07
Done.
| |
| 326 _state &= ~_STATE_IN_CALLBACK; | 327 _state &= ~_STATE_IN_CALLBACK; |
| 327 _checkState(wasInputPaused); | 328 _checkState(wasInputPaused); |
| 328 } | 329 } |
| 329 | 330 |
| 330 void _sendError(var error) { | 331 void _sendError(var error) { |
| 331 assert(!_isCanceled); | 332 assert(!_isCanceled); |
| 332 assert(!_isPaused); | 333 assert(!_isPaused); |
| 333 assert(!_inCallback); | 334 assert(!_inCallback); |
| 334 bool wasInputPaused = _isInputPaused; | 335 bool wasInputPaused = _isInputPaused; |
| 335 _state |= _STATE_IN_CALLBACK; | 336 _state |= _STATE_IN_CALLBACK; |
| 336 if (!_zone.inSameErrorZone(_Zone.current)) { | 337 if (!_zone.inSameErrorZone(Zone.current)) { |
| 337 // Errors are not allowed to traverse zone boundaries. | 338 // Errors are not allowed to traverse zone boundaries. |
| 338 _Zone.current.handleUncaughtError(error); | 339 Zone.current.handleUncaughtError(error); |
| 339 } else { | 340 } else { |
| 340 _zone.executePeriodicCallbackGuarded(() => _onError(error)); | 341 _zone.runGuarded1(_onError, error); |
|
Lasse Reichstein Nielsen
2013/09/23 14:24:12
Ditto.
floitsch
2013/09/23 17:12:07
Done.
| |
| 341 } | 342 } |
| 342 _state &= ~_STATE_IN_CALLBACK; | 343 _state &= ~_STATE_IN_CALLBACK; |
| 343 if (_cancelOnError) { | 344 if (_cancelOnError) { |
| 344 _cancel(); | 345 _cancel(); |
| 345 } | 346 } |
| 346 _checkState(wasInputPaused); | 347 _checkState(wasInputPaused); |
| 347 } | 348 } |
| 348 | 349 |
| 349 void _sendDone() { | 350 void _sendDone() { |
| 350 assert(!_isCanceled); | 351 assert(!_isCanceled); |
| 351 assert(!_isPaused); | 352 assert(!_isPaused); |
| 352 assert(!_inCallback); | 353 assert(!_inCallback); |
| 353 _state |= (_STATE_CANCELED | _STATE_CLOSED | _STATE_IN_CALLBACK); | 354 _state |= (_STATE_CANCELED | _STATE_CLOSED | _STATE_IN_CALLBACK); |
| 354 _zone.executeCallbackGuarded(_onDone); | 355 _zone.runGuarded(_onDone); |
| 355 _onCancel(); // No checkState after cancel, it is always the last event. | 356 _onCancel(); // No checkState after cancel, it is always the last event. |
| 356 _state &= ~_STATE_IN_CALLBACK; | 357 _state &= ~_STATE_IN_CALLBACK; |
| 357 } | 358 } |
| 358 | 359 |
| 359 /** | 360 /** |
| 360 * Call a hook function. | 361 * Call a hook function. |
| 361 * | 362 * |
| 362 * The call is properly wrapped in code to avoid other callbacks | 363 * The call is properly wrapped in code to avoid other callbacks |
| 363 * during the call, and it checks for state changes after the call | 364 * during the call, and it checks for state changes after the call |
| 364 * that should cause further callbacks. | 365 * that should cause further callbacks. |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 525 typedef void _DataHandler<T>(T value); | 526 typedef void _DataHandler<T>(T value); |
| 526 typedef void _ErrorHandler(error); | 527 typedef void _ErrorHandler(error); |
| 527 typedef void _DoneHandler(); | 528 typedef void _DoneHandler(); |
| 528 | 529 |
| 529 | 530 |
| 530 /** Default data handler, does nothing. */ | 531 /** Default data handler, does nothing. */ |
| 531 void _nullDataHandler(var value) {} | 532 void _nullDataHandler(var value) {} |
| 532 | 533 |
| 533 /** Default error handler, reports the error to the global handler. */ | 534 /** Default error handler, reports the error to the global handler. */ |
| 534 void _nullErrorHandler(error) { | 535 void _nullErrorHandler(error) { |
| 535 _Zone.current.handleUncaughtError(error); | 536 Zone.current.handleUncaughtError(error); |
| 536 } | 537 } |
| 537 | 538 |
| 538 /** Default done handler, does nothing. */ | 539 /** Default done handler, does nothing. */ |
| 539 void _nullDoneHandler() {} | 540 void _nullDoneHandler() {} |
| 540 | 541 |
| 541 | 542 |
| 542 /** A delayed event on a buffering stream subscription. */ | 543 /** A delayed event on a buffering stream subscription. */ |
| 543 abstract class _DelayedEvent { | 544 abstract class _DelayedEvent { |
| 544 /** Added as a linked list on the [StreamController]. */ | 545 /** Added as a linked list on the [StreamController]. */ |
| 545 _DelayedEvent next; | 546 _DelayedEvent next; |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 716 void cancel() {} | 717 void cancel() {} |
| 717 bool get isPaused => _pauseCounter > 0; | 718 bool get isPaused => _pauseCounter > 0; |
| 718 | 719 |
| 719 Future asFuture([futureValue]) => new _Future(); | 720 Future asFuture([futureValue]) => new _Future(); |
| 720 } | 721 } |
| 721 | 722 |
| 722 class _AsBroadcastStream<T> extends Stream<T> { | 723 class _AsBroadcastStream<T> extends Stream<T> { |
| 723 final Stream<T> _source; | 724 final Stream<T> _source; |
| 724 final _broadcastCallback _onListenHandler; | 725 final _broadcastCallback _onListenHandler; |
| 725 final _broadcastCallback _onCancelHandler; | 726 final _broadcastCallback _onCancelHandler; |
| 726 final _Zone _zone; | 727 final Zone _zone; |
| 727 | 728 |
| 728 _AsBroadcastStreamController<T> _controller; | 729 _AsBroadcastStreamController<T> _controller; |
| 729 StreamSubscription<T> _subscription; | 730 StreamSubscription<T> _subscription; |
| 730 | 731 |
| 731 _AsBroadcastStream(this._source, | 732 _AsBroadcastStream(this._source, |
| 732 this._onListenHandler, | 733 void onListenHandler(StreamSubscription subscription), |
| 733 this._onCancelHandler) | 734 void onCancelHandler(StreamSubscription subscription)) |
| 734 : _zone = _Zone.current { | 735 : _onListenHandler = Zone.current.registerCallback1(onListenHandler), |
| 736 _onCancelHandler = Zone.current.registerCallback1(onCancelHandler), | |
| 737 _zone = Zone.current { | |
| 735 _controller = new _AsBroadcastStreamController<T>(_onListen, _onCancel); | 738 _controller = new _AsBroadcastStreamController<T>(_onListen, _onCancel); |
| 736 // Keep zone alive until we are done doing callbacks. | |
| 737 _zone.expectCallback(); | |
| 738 } | 739 } |
| 739 | 740 |
| 740 bool get isBroadcast => true; | 741 bool get isBroadcast => true; |
| 741 | 742 |
| 742 StreamSubscription<T> listen(void onData(T data), | 743 StreamSubscription<T> listen(void onData(T data), |
| 743 { void onError(Object error), | 744 { void onError(Object error), |
| 744 void onDone(), | 745 void onDone(), |
| 745 bool cancelOnError}) { | 746 bool cancelOnError}) { |
| 746 if (_controller == null) { | 747 if (_controller == null) { |
| 747 // Return a dummy subscription backed by nothing, since | 748 // Return a dummy subscription backed by nothing, since |
| 748 // it won't ever receive any events. | 749 // it won't ever receive any events. |
| 749 return new _DummyStreamSubscription<T>(); | 750 return new _DummyStreamSubscription<T>(); |
| 750 } | 751 } |
| 751 if (_subscription == null) { | 752 if (_subscription == null) { |
| 752 _subscription = _source.listen(_controller.add, | 753 _subscription = _source.listen(_controller.add, |
| 753 onError: _controller.addError, | 754 onError: _controller.addError, |
| 754 onDone: _controller.close); | 755 onDone: _controller.close); |
| 755 } | 756 } |
| 756 if (onData == null) onData = _nullDataHandler; | 757 if (onData == null) onData = _nullDataHandler; |
| 757 if (onError == null) onError = _nullErrorHandler; | 758 if (onError == null) onError = _nullErrorHandler; |
| 758 if (onDone == null) onDone = _nullDoneHandler; | 759 if (onDone == null) onDone = _nullDoneHandler; |
| 759 cancelOnError = identical(true, cancelOnError); | 760 cancelOnError = identical(true, cancelOnError); |
| 760 return _controller._subscribe(onData, onError, onDone, cancelOnError); | 761 return _controller._subscribe(onData, onError, onDone, cancelOnError); |
| 761 } | 762 } |
| 762 | 763 |
| 763 void _onCancel() { | 764 void _onCancel() { |
| 764 bool shutdown = (_controller == null) || _controller.isClosed; | 765 bool shutdown = (_controller == null) || _controller.isClosed; |
| 765 if (_onCancelHandler != null) { | 766 if (_onCancelHandler != null) { |
| 766 _zone.executePeriodicCallbackGuarded( | 767 _zone.run1(_onCancelHandler, new _BroadcastSubscriptionWrapper(this)); |
|
Lasse Reichstein Nielsen
2013/09/23 14:24:12
runUnary?
floitsch
2013/09/23 17:12:07
Done.
| |
| 767 () => _onCancelHandler(new _BroadcastSubscriptionWrapper(this))); | |
| 768 } | 768 } |
| 769 if (shutdown) { | 769 if (shutdown) { |
| 770 if (_subscription != null) { | 770 if (_subscription != null) { |
| 771 _subscription.cancel(); | 771 _subscription.cancel(); |
| 772 _subscription = null; | 772 _subscription = null; |
| 773 } | 773 } |
| 774 _zone.cancelCallbackExpectation(); | |
| 775 } | 774 } |
| 776 } | 775 } |
| 777 | 776 |
| 778 void _onListen() { | 777 void _onListen() { |
| 779 if (_onListenHandler != null) { | 778 if (_onListenHandler != null) { |
| 780 _zone.executePeriodicCallbackGuarded( | 779 _zone.run1(_onListenHandler, new _BroadcastSubscriptionWrapper(this)); |
| 781 () => _onListenHandler(new _BroadcastSubscriptionWrapper(this))); | |
| 782 } | 780 } |
| 783 } | 781 } |
| 784 | 782 |
| 785 // Methods called from _BroadcastSubscriptionWrapper. | 783 // Methods called from _BroadcastSubscriptionWrapper. |
| 786 void _cancelSubscription() { | 784 void _cancelSubscription() { |
| 787 if (_subscription == null) return; | 785 if (_subscription == null) return; |
| 788 // Called by [_controller] when it has no subscribers left. | 786 // Called by [_controller] when it has no subscribers left. |
| 789 StreamSubscription subscription = _subscription; | 787 StreamSubscription subscription = _subscription; |
| 790 _subscription = null; | 788 _subscription = null; |
| 791 if (_controller._isEmpty) { | |
| 792 _zone.cancelCallbackExpectation(); | |
| 793 } | |
| 794 _controller = null; // Marks the stream as no longer listenable. | 789 _controller = null; // Marks the stream as no longer listenable. |
| 795 subscription.cancel(); | 790 subscription.cancel(); |
| 796 } | 791 } |
| 797 | 792 |
| 798 void _pauseSubscription(Future resumeSignal) { | 793 void _pauseSubscription(Future resumeSignal) { |
| 799 if (_subscription == null) return; | 794 if (_subscription == null) return; |
| 800 _subscription.pause(resumeSignal); | 795 _subscription.pause(resumeSignal); |
| 801 } | 796 } |
| 802 | 797 |
| 803 void _resumeSubscription() { | 798 void _resumeSubscription() { |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1000 _Future<bool> hasNext = _futureOrPrefetch; | 995 _Future<bool> hasNext = _futureOrPrefetch; |
| 1001 _clear(); | 996 _clear(); |
| 1002 hasNext._complete(false); | 997 hasNext._complete(false); |
| 1003 return; | 998 return; |
| 1004 } | 999 } |
| 1005 _subscription.pause(); | 1000 _subscription.pause(); |
| 1006 _futureOrPrefetch = null; | 1001 _futureOrPrefetch = null; |
| 1007 _state = _STATE_EXTRA_DONE; | 1002 _state = _STATE_EXTRA_DONE; |
| 1008 } | 1003 } |
| 1009 } | 1004 } |
| OLD | NEW |