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

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

Issue 11791045: Added toMultiSubscriber on Stream. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 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
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 // 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 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 * * [_onSubscriberStateChange]: Called when receiving the first subscriber or 396 * * [_onSubscriberStateChange]: Called when receiving the first subscriber or
397 * when losing the last subscriber. 397 * when losing the last subscriber.
398 * * [_onPauseStateChange]: Called when entering or leaving paused mode. 398 * * [_onPauseStateChange]: Called when entering or leaving paused mode.
399 * * [_hasSubscribers]: Test whether there are currently any subscribers. 399 * * [_hasSubscribers]: Test whether there are currently any subscribers.
400 * * [_isPaused]: Test whether the stream is currently paused. 400 * * [_isPaused]: Test whether the stream is currently paused.
401 * The user should not add new events while the stream is paused, but if it 401 * The user should not add new events while the stream is paused, but if it
402 * happens anyway, the stream will enqueue the events just as when new events 402 * happens anyway, the stream will enqueue the events just as when new events
403 * arrive while still firing an old event. 403 * arrive while still firing an old event.
404 */ 404 */
405 class _SingleStreamImpl<T> extends _StreamImpl<T> { 405 class _SingleStreamImpl<T> extends _StreamImpl<T> {
406 _StreamSubscriptionImpl _subscriber = null; 406 _StreamListener _subscriber = null;
407
408 Stream<T> toMultiSubscriber() {
409 _MultiStreamImpl<T> multiStream = new _MultiStreamImpl();
410 listen(multiStream._add,
floitsch 2013/01/08 14:06:00 as discussed: don't listen right away.
Lasse Reichstein Nielsen 2013/01/09 15:19:17 Done.
411 onError: multiStream._signalError,
412 onDone: multiStream._close);
413 return multiStream;
414 }
407 415
408 /** Whether one or more active subscribers have requested a pause. */ 416 /** Whether one or more active subscribers have requested a pause. */
409 bool get _isPaused => !_hasSubscribers || super._isPaused; 417 bool get _isPaused => !_hasSubscribers || super._isPaused;
410 418
411 /** Whether there is currently a subscriber on this [Stream]. */ 419 /** Whether there is currently a subscriber on this [Stream]. */
412 bool get _hasSubscribers => _subscriber != null; 420 bool get _hasSubscribers => _subscriber != null;
413 421
414 // ------------------------------------------------------------------- 422 // -------------------------------------------------------------------
415 // Internal implementation. 423 // Internal implementation.
416 424
417 /** 425 /**
418 * Create the new subscription object. 426 * Create the new subscription object.
419 */ 427 */
420 _StreamSubscriptionImpl<T> _createSubscription( 428 _StreamSubscriptionImpl<T> _createSubscription(
421 void onData(T data), 429 void onData(T data),
422 void onError(AsyncError error), 430 void onError(AsyncError error),
423 void onDone(), 431 void onDone(),
424 bool unsubscribeOnError) { 432 bool unsubscribeOnError) {
425 return new _StreamSubscriptionImpl<T>( 433 return new _StreamSubscriptionImpl<T>(
426 this, onData, onError, onDone, unsubscribeOnError); 434 this, onData, onError, onDone, unsubscribeOnError);
427 } 435 }
428 436
429 void _addListener(_StreamSubscriptionImpl subscription) { 437 void _addListener(_StreamListener subscription) {
430 if (_hasSubscribers) { 438 if (_hasSubscribers) {
431 throw new StateError("Stream has already subscriber."); 439 throw new StateError("Stream already has subscriber.");
432 } 440 }
433 _subscriber = subscription; 441 _subscriber = subscription;
434 subscription._setSubscribed(0); 442 subscription._setSubscribed(0);
435 _onSubscriptionStateChange(); 443 _onSubscriptionStateChange();
436 // TODO(floitsch): Should this be delayed? 444 // TODO(floitsch): Should this be delayed?
437 _handlePendingEvents(); 445 _handlePendingEvents();
438 } 446 }
439 447
440 /** 448 /**
441 * Handle a cancel requested from a [_StreamSubscriptionImpl]. 449 * Handle a cancel requested from a [_StreamSubscriptionImpl].
442 * 450 *
443 * This method is called from [_StreamSubscriptionImpl.cancel]. 451 * This method is called from [_StreamSubscriptionImpl.cancel].
444 * 452 *
445 * If an event is currently firing, the cancel is delayed 453 * If an event is currently firing, the cancel is delayed
446 * until after the subscriber has received the event. 454 * until after the subscriber has received the event.
447 */ 455 */
448 void _cancel(_StreamSubscriptionImpl subscriber) { 456 void _cancel(_StreamListener subscriber) {
449 assert(identical(subscriber._source, this)); 457 assert(identical(subscriber._source, this));
450 // We allow unsubscribing the currently firing subscription during 458 // We allow unsubscribing the currently firing subscription during
451 // the event firing, because it is indistinguishable from delaying it since 459 // the event firing, because it is indistinguishable from delaying it since
452 // that event has already received the event. 460 // that event has already received the event.
453 if (!identical(_subscriber, subscriber)) { 461 if (!identical(_subscriber, subscriber)) {
454 // You may unsubscribe more than once, only the first one counts. 462 // You may unsubscribe more than once, only the first one counts.
455 return; 463 return;
456 } 464 }
457 _subscriber = null; 465 _subscriber = null;
458 int timesPaused = subscriber._setUnsubscribed(); 466 int timesPaused = subscriber._setUnsubscribed();
459 _updatePauseCount(-timesPaused); 467 _updatePauseCount(-timesPaused);
460 if (timesPaused > 0) { 468 if (timesPaused > 0) {
461 _onPauseStateChange(); 469 _onPauseStateChange();
462 } 470 }
463 _onSubscriptionStateChange(); 471 _onSubscriptionStateChange();
464 } 472 }
465 473
466 void _forEachSubscriber( 474 void _forEachSubscriber(
467 void action(_StreamSubscriptionImpl<T> subscription)) { 475 void action(_StreamListener<T> subscription)) {
468 _StreamSubscriptionImpl subscription = _subscriber; 476 _StreamListener subscription = _subscriber;
469 assert(subscription != null); 477 assert(subscription != null);
470 _startFiring(); 478 _startFiring();
471 action(subscription); 479 action(subscription);
472 _endFiring(); 480 _endFiring();
473 } 481 }
474 } 482 }
475 483
476 // ------------------------------------------------------------------- 484 // -------------------------------------------------------------------
477 // Default implementation of a stream with subscribers. 485 // Default implementation of a stream with subscribers.
478 // ------------------------------------------------------------------- 486 // -------------------------------------------------------------------
(...skipping 28 matching lines...) Expand all
507 class _MultiStreamImpl<T> extends _StreamImpl<T> 515 class _MultiStreamImpl<T> extends _StreamImpl<T>
508 implements _InternalLinkList { 516 implements _InternalLinkList {
509 // Link list implementation (mixin when possible). 517 // Link list implementation (mixin when possible).
510 _InternalLink _nextLink; 518 _InternalLink _nextLink;
511 _InternalLink _previousLink; 519 _InternalLink _previousLink;
512 520
513 _MultiStreamImpl() { 521 _MultiStreamImpl() {
514 _nextLink = _previousLink = this; 522 _nextLink = _previousLink = this;
515 } 523 }
516 524
525 Stream<T> toMultiSubscriber() => this;
526
517 // ------------------------------------------------------------------ 527 // ------------------------------------------------------------------
518 // Helper functions that can be overridden in subclasses. 528 // Helper functions that can be overridden in subclasses.
519 529
520 /** Whether there are currently any subscribers on this [Stream]. */ 530 /** Whether there are currently any subscribers on this [Stream]. */
521 bool get _hasSubscribers => !_InternalLinkList.isEmpty(this); 531 bool get _hasSubscribers => !_InternalLinkList.isEmpty(this);
522 532
523 /** 533 /**
524 * Create the new subscription object. 534 * Create the new subscription object.
525 */ 535 */
526 _StreamListener<T> _createSubscription( 536 _StreamListener<T> _createSubscription(
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 if (_isComplete) { 1018 if (_isComplete) {
1009 throw new StateError("Subscription has been canceled."); 1019 throw new StateError("Subscription has been canceled.");
1010 } 1020 }
1011 if (_timer != null) { 1021 if (_timer != null) {
1012 _timer.cancel(); 1022 _timer.cancel();
1013 _timer = null; 1023 _timer = null;
1014 } 1024 }
1015 _pauseCount = 0; 1025 _pauseCount = 0;
1016 } 1026 }
1017 } 1027 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698