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

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

Issue 48733002: Fix bugs in StreamController.addStream. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Remove StreamControllerSink. The optional cancelOnError on addStream is only in controller. Created 7 years, 1 month 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 // ------------------------------------------------------------------- 7 // -------------------------------------------------------------------
8 // Controller for creating and adding events to a stream. 8 // Controller for creating and adding events to a stream.
9 // ------------------------------------------------------------------- 9 // -------------------------------------------------------------------
10 10
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 */ 337 */
338 Error _badEventState() { 338 Error _badEventState() {
339 if (isClosed) { 339 if (isClosed) {
340 return new StateError("Cannot add event after closing"); 340 return new StateError("Cannot add event after closing");
341 } 341 }
342 assert(_isAddingStream); 342 assert(_isAddingStream);
343 return new StateError("Cannot add event while adding a stream"); 343 return new StateError("Cannot add event while adding a stream");
344 } 344 }
345 345
346 // StreamSink interface. 346 // StreamSink interface.
347 Future addStream(Stream<T> source) { 347 /**
348 * Receives events from [source] and puts them into this controller's stream.
349 *
350 * Returns a future which completes when the stream adding is done.
351 *
352 * Events must not be added directly to this controller using [add],
353 * [addError], [close] or [addStream], until the returned future
354 * is complete.
355 *
356 * Data and error events are forwarded to this controller's stream. A done
357 * event on the source will end the `addStream` operation and complete the
358 * returned future.
359 *
360 * If [cancelOnError] is true, only the first error on [source] is
361 * forwarded to the controller's stream, and the `addStream` ends
362 * after theis. If [cancelOnError] is false, all errors are forwarded
363 * and only a done event from
364 */
365 Future addStream(Stream<T> source, { bool cancelOnError: true }) {
348 if (!_mayAddEvent) throw _badEventState(); 366 if (!_mayAddEvent) throw _badEventState();
349 if (_isCanceled) return new _Future.immediate(null); 367 if (_isCanceled) return new _Future.immediate(null);
350 _StreamControllerAddStreamState addState = 368 _StreamControllerAddStreamState addState =
351 new _StreamControllerAddStreamState(this, _varData, source); 369 new _StreamControllerAddStreamState(this, _varData, source,
370 cancelOnError);
352 _varData = addState; 371 _varData = addState;
353 _state |= _STATE_ADDSTREAM; 372 _state |= _STATE_ADDSTREAM;
354 return addState.addStreamFuture; 373 return addState.addStreamFuture;
355 } 374 }
356 375
357 Future get done => _ensureDoneFuture(); 376 Future get done => _ensureDoneFuture();
358 377
359 Future _ensureDoneFuture() { 378 Future _ensureDoneFuture() {
360 if (_doneFuture == null) { 379 if (_doneFuture == null) {
361 _doneFuture = new _Future(); 380 _doneFuture = new _Future();
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 throw new StateError("Stream has already been listened to."); 466 throw new StateError("Stream has already been listened to.");
448 } 467 }
449 _ControllerSubscription subscription = 468 _ControllerSubscription subscription =
450 new _ControllerSubscription(this, cancelOnError); 469 new _ControllerSubscription(this, cancelOnError);
451 470
452 _PendingEvents pendingEvents = _pendingEvents; 471 _PendingEvents pendingEvents = _pendingEvents;
453 _state |= _STATE_SUBSCRIBED; 472 _state |= _STATE_SUBSCRIBED;
454 if (_isAddingStream) { 473 if (_isAddingStream) {
455 _StreamControllerAddStreamState addState = _varData; 474 _StreamControllerAddStreamState addState = _varData;
456 addState.varData = subscription; 475 addState.varData = subscription;
476 addState.resume();
457 } else { 477 } else {
458 _varData = subscription; 478 _varData = subscription;
459 } 479 }
460 subscription._setPendingEvents(pendingEvents); 480 subscription._setPendingEvents(pendingEvents);
461 subscription._guardCallback(() { 481 subscription._guardCallback(() {
462 _runGuarded(_onListen); 482 _runGuarded(_onListen);
463 }); 483 });
464 484
465 return subscription; 485 return subscription;
466 } 486 }
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 } 646 }
627 647
628 void _onResume() { 648 void _onResume() {
629 _controller._recordResume(this); 649 _controller._recordResume(this);
630 } 650 }
631 } 651 }
632 652
633 653
634 /** A class that exposes only the [StreamSink] interface of an object. */ 654 /** A class that exposes only the [StreamSink] interface of an object. */
635 class _StreamSinkWrapper<T> implements StreamSink<T> { 655 class _StreamSinkWrapper<T> implements StreamSink<T> {
636 final StreamSink _target; 656 final StreamController _target;
637 _StreamSinkWrapper(this._target); 657 _StreamSinkWrapper(this._target);
638 void add(T data) { _target.add(data); } 658 void add(T data) { _target.add(data); }
639 void addError(Object error, [StackTrace stackTrace]) { 659 void addError(Object error, [StackTrace stackTrace]) {
640 _target.addError(error); 660 _target.addError(error);
641 } 661 }
642 Future close() => _target.close(); 662 Future close() => _target.close();
643 Future addStream(Stream<T> source) => _target.addStream(source); 663 Future addStream(Stream<T> source, { bool cancelOnError: true})
664 => _target.addStream(source, cancelOnError: cancelOnError);
644 Future get done => _target.done; 665 Future get done => _target.done;
645 } 666 }
646 667
647 /** 668 /**
648 * Object containing the state used to handle [StreamController.addStream]. 669 * Object containing the state used to handle [StreamController.addStream].
649 */ 670 */
650 class _AddStreamState<T> { 671 class _AddStreamState<T> {
651 // [_Future] returned by call to addStream. 672 // [_Future] returned by call to addStream.
652 _Future addStreamFuture; 673 final _Future addStreamFuture;
653 674
654 // Subscription on stream argument to addStream. 675 // Subscription on stream argument to addStream.
655 StreamSubscription addSubscription; 676 final StreamSubscription addSubscription;
656 677
657 _AddStreamState(_EventSink<T> controller, Stream source) 678 _AddStreamState(_EventSink<T> controller, Stream source, bool cancelOnError)
658 : addStreamFuture = new _Future(), 679 : addStreamFuture = new _Future(),
659 addSubscription = source.listen(controller._add, 680 addSubscription = source.listen(controller._add,
660 onError: controller._addError, 681 onError: cancelOnError
682 ? makeErrorHandler(controller)
683 : controller._addError,
661 onDone: controller._close, 684 onDone: controller._close,
662 cancelOnError: true); 685 cancelOnError: cancelOnError);
686
687 static makeErrorHandler(_EventSink controller) =>
688 (e, StackTrace s) {
689 controller._addError(e, s);
690 controller._close();
691 };
663 692
664 void pause() { 693 void pause() {
665 addSubscription.pause(); 694 addSubscription.pause();
666 } 695 }
667 696
668 void resume() { 697 void resume() {
669 addSubscription.resume(); 698 addSubscription.resume();
670 } 699 }
671 700
672 void cancel() { 701 void cancel() {
673 addSubscription.cancel(); 702 addSubscription.cancel();
674 complete(); 703 complete();
675 } 704 }
676 705
677 void complete() { 706 void complete() {
678 addStreamFuture._asyncComplete(null); 707 addStreamFuture._asyncComplete(null);
679 } 708 }
680 } 709 }
681 710
682 class _StreamControllerAddStreamState<T> extends _AddStreamState<T> { 711 class _StreamControllerAddStreamState<T> extends _AddStreamState<T> {
683 // The subscription or pending data of a _StreamController. 712 // The subscription or pending data of a _StreamController.
684 // Stored here because we reuse the `_varData` field in the _StreamController 713 // Stored here because we reuse the `_varData` field in the _StreamController
685 // to store this state object. 714 // to store this state object.
686 var varData; 715 var varData;
687 716
688 _StreamControllerAddStreamState(_StreamController controller, 717 _StreamControllerAddStreamState(_StreamController controller,
689 this.varData, 718 this.varData,
690 Stream source) : super(controller, source) { 719 Stream source,
720 bool cancelOnError)
721 : super(controller, source, cancelOnError) {
691 if (controller.isPaused) { 722 if (controller.isPaused) {
692 addSubscription.pause(); 723 addSubscription.pause();
693 } 724 }
694 } 725 }
695 } 726 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698