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

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: Addressed comments. Added test. Fixed typos. 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
« no previous file with comments | « sdk/lib/async/broadcast_stream_controller.dart ('k') | tests/co19/co19-co19.status » ('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 // ------------------------------------------------------------------- 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 source stream 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 this. If [cancelOnError] is false, all errors are forwarded
363 * and only a done event will end the `addStream`.
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,
370 _varData,
371 source,
372 cancelOnError);
352 _varData = addState; 373 _varData = addState;
353 _state |= _STATE_ADDSTREAM; 374 _state |= _STATE_ADDSTREAM;
354 return addState.addStreamFuture; 375 return addState.addStreamFuture;
355 } 376 }
356 377
357 Future get done => _ensureDoneFuture(); 378 Future get done => _ensureDoneFuture();
358 379
359 Future _ensureDoneFuture() { 380 Future _ensureDoneFuture() {
360 if (_doneFuture == null) { 381 if (_doneFuture == null) {
361 _doneFuture = new _Future(); 382 _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."); 468 throw new StateError("Stream has already been listened to.");
448 } 469 }
449 _ControllerSubscription subscription = 470 _ControllerSubscription subscription =
450 new _ControllerSubscription(this, cancelOnError); 471 new _ControllerSubscription(this, cancelOnError);
451 472
452 _PendingEvents pendingEvents = _pendingEvents; 473 _PendingEvents pendingEvents = _pendingEvents;
453 _state |= _STATE_SUBSCRIBED; 474 _state |= _STATE_SUBSCRIBED;
454 if (_isAddingStream) { 475 if (_isAddingStream) {
455 _StreamControllerAddStreamState addState = _varData; 476 _StreamControllerAddStreamState addState = _varData;
456 addState.varData = subscription; 477 addState.varData = subscription;
478 addState.resume();
457 } else { 479 } else {
458 _varData = subscription; 480 _varData = subscription;
459 } 481 }
460 subscription._setPendingEvents(pendingEvents); 482 subscription._setPendingEvents(pendingEvents);
461 subscription._guardCallback(() { 483 subscription._guardCallback(() {
462 _runGuarded(_onListen); 484 _runGuarded(_onListen);
463 }); 485 });
464 486
465 return subscription; 487 return subscription;
466 } 488 }
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 } 648 }
627 649
628 void _onResume() { 650 void _onResume() {
629 _controller._recordResume(this); 651 _controller._recordResume(this);
630 } 652 }
631 } 653 }
632 654
633 655
634 /** A class that exposes only the [StreamSink] interface of an object. */ 656 /** A class that exposes only the [StreamSink] interface of an object. */
635 class _StreamSinkWrapper<T> implements StreamSink<T> { 657 class _StreamSinkWrapper<T> implements StreamSink<T> {
636 final StreamSink _target; 658 final StreamController _target;
637 _StreamSinkWrapper(this._target); 659 _StreamSinkWrapper(this._target);
638 void add(T data) { _target.add(data); } 660 void add(T data) { _target.add(data); }
639 void addError(Object error, [StackTrace stackTrace]) { 661 void addError(Object error, [StackTrace stackTrace]) {
640 _target.addError(error); 662 _target.addError(error);
641 } 663 }
642 Future close() => _target.close(); 664 Future close() => _target.close();
643 Future addStream(Stream<T> source) => _target.addStream(source); 665 Future addStream(Stream<T> source, { bool cancelOnError: true})
666 => _target.addStream(source, cancelOnError: cancelOnError);
644 Future get done => _target.done; 667 Future get done => _target.done;
645 } 668 }
646 669
647 /** 670 /**
648 * Object containing the state used to handle [StreamController.addStream]. 671 * Object containing the state used to handle [StreamController.addStream].
649 */ 672 */
650 class _AddStreamState<T> { 673 class _AddStreamState<T> {
651 // [_Future] returned by call to addStream. 674 // [_Future] returned by call to addStream.
652 _Future addStreamFuture; 675 final _Future addStreamFuture;
653 676
654 // Subscription on stream argument to addStream. 677 // Subscription on stream argument to addStream.
655 StreamSubscription addSubscription; 678 final StreamSubscription addSubscription;
656 679
657 _AddStreamState(_EventSink<T> controller, Stream source) 680 _AddStreamState(_EventSink<T> controller, Stream source, bool cancelOnError)
658 : addStreamFuture = new _Future(), 681 : addStreamFuture = new _Future(),
659 addSubscription = source.listen(controller._add, 682 addSubscription = source.listen(controller._add,
660 onError: controller._addError, 683 onError: cancelOnError
684 ? makeErrorHandler(controller)
685 : controller._addError,
661 onDone: controller._close, 686 onDone: controller._close,
662 cancelOnError: true); 687 cancelOnError: cancelOnError);
688
689 static makeErrorHandler(_EventSink controller) =>
690 (e, StackTrace s) {
691 controller._addError(e, s);
692 controller._close();
693 };
663 694
664 void pause() { 695 void pause() {
665 addSubscription.pause(); 696 addSubscription.pause();
666 } 697 }
667 698
668 void resume() { 699 void resume() {
669 addSubscription.resume(); 700 addSubscription.resume();
670 } 701 }
671 702
672 void cancel() { 703 void cancel() {
673 addSubscription.cancel(); 704 addSubscription.cancel();
674 complete(); 705 complete();
675 } 706 }
676 707
677 void complete() { 708 void complete() {
678 addStreamFuture._asyncComplete(null); 709 addStreamFuture._asyncComplete(null);
679 } 710 }
680 } 711 }
681 712
682 class _StreamControllerAddStreamState<T> extends _AddStreamState<T> { 713 class _StreamControllerAddStreamState<T> extends _AddStreamState<T> {
683 // The subscription or pending data of a _StreamController. 714 // The subscription or pending data of a _StreamController.
684 // Stored here because we reuse the `_varData` field in the _StreamController 715 // Stored here because we reuse the `_varData` field in the _StreamController
685 // to store this state object. 716 // to store this state object.
686 var varData; 717 var varData;
687 718
688 _StreamControllerAddStreamState(_StreamController controller, 719 _StreamControllerAddStreamState(_StreamController controller,
689 this.varData, 720 this.varData,
690 Stream source) : super(controller, source) { 721 Stream source,
722 bool cancelOnError)
723 : super(controller, source, cancelOnError) {
691 if (controller.isPaused) { 724 if (controller.isPaused) {
692 addSubscription.pause(); 725 addSubscription.pause();
693 } 726 }
694 } 727 }
695 } 728 }
OLDNEW
« no previous file with comments | « sdk/lib/async/broadcast_stream_controller.dart ('k') | tests/co19/co19-co19.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698