| 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 // States shared by single/multi stream implementations. | 7 // States shared by single/multi stream implementations. |
| 8 | 8 |
| 9 /// Initial and default state where the stream can receive and send events. | 9 /// Initial and default state where the stream can receive and send events. |
| 10 const int _STREAM_OPEN = 0; | 10 const int _STREAM_OPEN = 0; |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 * * [_onSubscriberStateChange]: Called when receiving the first subscriber or | 405 * * [_onSubscriberStateChange]: Called when receiving the first subscriber or |
| 406 * when losing the last subscriber. | 406 * when losing the last subscriber. |
| 407 * * [_onPauseStateChange]: Called when entering or leaving paused mode. | 407 * * [_onPauseStateChange]: Called when entering or leaving paused mode. |
| 408 * * [_hasSubscribers]: Test whether there are currently any subscribers. | 408 * * [_hasSubscribers]: Test whether there are currently any subscribers. |
| 409 * * [_isPaused]: Test whether the stream is currently paused. | 409 * * [_isPaused]: Test whether the stream is currently paused. |
| 410 * The user should not add new events while the stream is paused, but if it | 410 * The user should not add new events while the stream is paused, but if it |
| 411 * happens anyway, the stream will enqueue the events just as when new events | 411 * happens anyway, the stream will enqueue the events just as when new events |
| 412 * arrive while still firing an old event. | 412 * arrive while still firing an old event. |
| 413 */ | 413 */ |
| 414 class _SingleStreamImpl<T> extends _StreamImpl<T> { | 414 class _SingleStreamImpl<T> extends _StreamImpl<T> { |
| 415 _StreamSubscriptionImpl _subscriber = null; | 415 _StreamListener _subscriber = null; |
| 416 |
| 417 Stream<T> asMultiSubscriberStream() { |
| 418 return new _ForwardingMultiStream<T, T>().._source = this; |
| 419 } |
| 416 | 420 |
| 417 /** Whether one or more active subscribers have requested a pause. */ | 421 /** Whether one or more active subscribers have requested a pause. */ |
| 418 bool get _isPaused => !_hasSubscribers || super._isPaused; | 422 bool get _isPaused => !_hasSubscribers || super._isPaused; |
| 419 | 423 |
| 420 /** Whether there is currently a subscriber on this [Stream]. */ | 424 /** Whether there is currently a subscriber on this [Stream]. */ |
| 421 bool get _hasSubscribers => _subscriber != null; | 425 bool get _hasSubscribers => _subscriber != null; |
| 422 | 426 |
| 423 // ------------------------------------------------------------------- | 427 // ------------------------------------------------------------------- |
| 424 // Internal implementation. | 428 // Internal implementation. |
| 425 | 429 |
| 426 /** | 430 /** |
| 427 * Create the new subscription object. | 431 * Create the new subscription object. |
| 428 */ | 432 */ |
| 429 _StreamSubscriptionImpl<T> _createSubscription( | 433 _StreamSubscriptionImpl<T> _createSubscription( |
| 430 void onData(T data), | 434 void onData(T data), |
| 431 void onError(AsyncError error), | 435 void onError(AsyncError error), |
| 432 void onDone(), | 436 void onDone(), |
| 433 bool unsubscribeOnError) { | 437 bool unsubscribeOnError) { |
| 434 return new _StreamSubscriptionImpl<T>( | 438 return new _StreamSubscriptionImpl<T>( |
| 435 this, onData, onError, onDone, unsubscribeOnError); | 439 this, onData, onError, onDone, unsubscribeOnError); |
| 436 } | 440 } |
| 437 | 441 |
| 438 void _addListener(_StreamSubscriptionImpl subscription) { | 442 void _addListener(_StreamListener subscription) { |
| 439 if (_hasSubscribers) { | 443 if (_hasSubscribers) { |
| 440 throw new StateError("Stream has already subscriber."); | 444 throw new StateError("Stream already has subscriber."); |
| 441 } | 445 } |
| 442 _subscriber = subscription; | 446 _subscriber = subscription; |
| 443 subscription._setSubscribed(0); | 447 subscription._setSubscribed(0); |
| 444 _onSubscriptionStateChange(); | 448 _onSubscriptionStateChange(); |
| 445 if (_hasPendingEvent) { | 449 if (_hasPendingEvent) { |
| 446 new Timer(0, (_) { | 450 new Timer(0, (_) { |
| 447 _handlePendingEvents(); | 451 _handlePendingEvents(); |
| 448 }); | 452 }); |
| 449 } | 453 } |
| 450 } | 454 } |
| 451 | 455 |
| 452 /** | 456 /** |
| 453 * Handle a cancel requested from a [_StreamSubscriptionImpl]. | 457 * Handle a cancel requested from a [_StreamSubscriptionImpl]. |
| 454 * | 458 * |
| 455 * This method is called from [_StreamSubscriptionImpl.cancel]. | 459 * This method is called from [_StreamSubscriptionImpl.cancel]. |
| 456 * | 460 * |
| 457 * If an event is currently firing, the cancel is delayed | 461 * If an event is currently firing, the cancel is delayed |
| 458 * until after the subscriber has received the event. | 462 * until after the subscriber has received the event. |
| 459 */ | 463 */ |
| 460 void _cancel(_StreamSubscriptionImpl subscriber) { | 464 void _cancel(_StreamListener subscriber) { |
| 461 assert(identical(subscriber._source, this)); | 465 assert(identical(subscriber._source, this)); |
| 462 // We allow unsubscribing the currently firing subscription during | 466 // We allow unsubscribing the currently firing subscription during |
| 463 // the event firing, because it is indistinguishable from delaying it since | 467 // the event firing, because it is indistinguishable from delaying it since |
| 464 // that event has already received the event. | 468 // that event has already received the event. |
| 465 if (!identical(_subscriber, subscriber)) { | 469 if (!identical(_subscriber, subscriber)) { |
| 466 // You may unsubscribe more than once, only the first one counts. | 470 // You may unsubscribe more than once, only the first one counts. |
| 467 return; | 471 return; |
| 468 } | 472 } |
| 469 _subscriber = null; | 473 _subscriber = null; |
| 470 int timesPaused = subscriber._setUnsubscribed(); | 474 int timesPaused = subscriber._setUnsubscribed(); |
| 471 _updatePauseCount(-timesPaused); | 475 _updatePauseCount(-timesPaused); |
| 472 if (timesPaused > 0) { | 476 if (timesPaused > 0) { |
| 473 _onPauseStateChange(); | 477 _onPauseStateChange(); |
| 474 } | 478 } |
| 475 _onSubscriptionStateChange(); | 479 _onSubscriptionStateChange(); |
| 476 } | 480 } |
| 477 | 481 |
| 478 void _forEachSubscriber( | 482 void _forEachSubscriber( |
| 479 void action(_StreamSubscriptionImpl<T> subscription)) { | 483 void action(_StreamListener<T> subscription)) { |
| 480 _StreamSubscriptionImpl subscription = _subscriber; | 484 _StreamListener subscription = _subscriber; |
| 481 assert(subscription != null); | 485 assert(subscription != null); |
| 482 _startFiring(); | 486 _startFiring(); |
| 483 action(subscription); | 487 action(subscription); |
| 484 _endFiring(); | 488 _endFiring(); |
| 485 } | 489 } |
| 486 } | 490 } |
| 487 | 491 |
| 488 // ------------------------------------------------------------------- | 492 // ------------------------------------------------------------------- |
| 489 // Default implementation of a stream with subscribers. | 493 // Default implementation of a stream with subscribers. |
| 490 // ------------------------------------------------------------------- | 494 // ------------------------------------------------------------------- |
| (...skipping 28 matching lines...) Expand all Loading... |
| 519 class _MultiStreamImpl<T> extends _StreamImpl<T> | 523 class _MultiStreamImpl<T> extends _StreamImpl<T> |
| 520 implements _InternalLinkList { | 524 implements _InternalLinkList { |
| 521 // Link list implementation (mixin when possible). | 525 // Link list implementation (mixin when possible). |
| 522 _InternalLink _nextLink; | 526 _InternalLink _nextLink; |
| 523 _InternalLink _previousLink; | 527 _InternalLink _previousLink; |
| 524 | 528 |
| 525 _MultiStreamImpl() { | 529 _MultiStreamImpl() { |
| 526 _nextLink = _previousLink = this; | 530 _nextLink = _previousLink = this; |
| 527 } | 531 } |
| 528 | 532 |
| 533 Stream<T> asMultiSubscriberStream() => this; |
| 534 |
| 529 // ------------------------------------------------------------------ | 535 // ------------------------------------------------------------------ |
| 530 // Helper functions that can be overridden in subclasses. | 536 // Helper functions that can be overridden in subclasses. |
| 531 | 537 |
| 532 /** Whether there are currently any subscribers on this [Stream]. */ | 538 /** Whether there are currently any subscribers on this [Stream]. */ |
| 533 bool get _hasSubscribers => !_InternalLinkList.isEmpty(this); | 539 bool get _hasSubscribers => !_InternalLinkList.isEmpty(this); |
| 534 | 540 |
| 535 /** | 541 /** |
| 536 * Create the new subscription object. | 542 * Create the new subscription object. |
| 537 */ | 543 */ |
| 538 _StreamListener<T> _createSubscription( | 544 _StreamListener<T> _createSubscription( |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1074 if (_isComplete) { | 1080 if (_isComplete) { |
| 1075 throw new StateError("Subscription has been canceled."); | 1081 throw new StateError("Subscription has been canceled."); |
| 1076 } | 1082 } |
| 1077 if (_timer != null) { | 1083 if (_timer != null) { |
| 1078 _timer.cancel(); | 1084 _timer.cancel(); |
| 1079 _timer = null; | 1085 _timer = null; |
| 1080 } | 1086 } |
| 1081 _pauseCount = 0; | 1087 _pauseCount = 0; |
| 1082 } | 1088 } |
| 1083 } | 1089 } |
| OLD | NEW |