| 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 // ------------------------------------------------------------------- | 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 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 * After closing, no further events may be added using [add] or [addError]. | 413 * After closing, no further events may be added using [add] or [addError]. |
| 414 * | 414 * |
| 415 * You are allowed to close the controller more than once, but only the first | 415 * You are allowed to close the controller more than once, but only the first |
| 416 * call has any effect. | 416 * call has any effect. |
| 417 * | 417 * |
| 418 * The first time a controller is closed, a "done" event is sent to its | 418 * The first time a controller is closed, a "done" event is sent to its |
| 419 * stream. | 419 * stream. |
| 420 */ | 420 */ |
| 421 Future close() { | 421 Future close() { |
| 422 if (isClosed) { | 422 if (isClosed) { |
| 423 _ensureDoneFuture(); | 423 return _ensureDoneFuture(); |
| 424 return _doneFuture; | |
| 425 } | 424 } |
| 426 if (!_mayAddEvent) throw _badEventState(); | 425 if (!_mayAddEvent) throw _badEventState(); |
| 427 _state |= _STATE_CLOSED; | 426 _state |= _STATE_CLOSED; |
| 428 if (hasListener) { | 427 if (hasListener) { |
| 429 _sendDone(); | 428 _sendDone(); |
| 430 } else if (_isInitialState) { | 429 } else if (_isInitialState) { |
| 431 _ensurePendingEvents().add(const _DelayedDone()); | 430 _ensurePendingEvents().add(const _DelayedDone()); |
| 432 } | 431 } |
| 433 _ensureDoneFuture(); | 432 return _ensureDoneFuture(); |
| 434 return _doneFuture; | |
| 435 } | 433 } |
| 436 | 434 |
| 437 // EventSink interface. Used by the [addStream] events. | 435 // EventSink interface. Used by the [addStream] events. |
| 438 | 436 |
| 439 // Add data event, used both by the [addStream] events and by [add]. | 437 // Add data event, used both by the [addStream] events and by [add]. |
| 440 void _add(T value) { | 438 void _add(T value) { |
| 441 if (hasListener) { | 439 if (hasListener) { |
| 442 _sendData(value); | 440 _sendData(value); |
| 443 } else if (_isInitialState) { | 441 } else if (_isInitialState) { |
| 444 _ensurePendingEvents().add(new _DelayedData<T>(value)); | 442 _ensurePendingEvents().add(new _DelayedData<T>(value)); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 } | 480 } |
| 483 subscription._setPendingEvents(pendingEvents); | 481 subscription._setPendingEvents(pendingEvents); |
| 484 subscription._guardCallback(() { | 482 subscription._guardCallback(() { |
| 485 _runGuarded(_onListen); | 483 _runGuarded(_onListen); |
| 486 }); | 484 }); |
| 487 | 485 |
| 488 return subscription; | 486 return subscription; |
| 489 } | 487 } |
| 490 | 488 |
| 491 Future _recordCancel(StreamSubscription<T> subscription) { | 489 Future _recordCancel(StreamSubscription<T> subscription) { |
| 490 // When we cancel, we first cancel any stream being added, |
| 491 // Then we call _onCancel, and finally the _doneFuture is completed. |
| 492 // If either of addStream's cancel or _onCancel returns a future, |
| 493 // we wait for it before continuing. |
| 494 // Any error during this process ends up in the returned future. |
| 495 // If more errors happen, we act as if it happens inside nested try/finallys |
| 496 // or whenComplete calls, and only the last error ends up in the |
| 497 // returned future. |
| 498 Future result; |
| 492 if (_isAddingStream) { | 499 if (_isAddingStream) { |
| 493 _StreamControllerAddStreamState addState = _varData; | 500 _StreamControllerAddStreamState addState = _varData; |
| 494 addState.cancel(); | 501 result = addState.cancel(); |
| 495 } | 502 } |
| 496 _varData = null; | 503 _varData = null; |
| 497 _state = | 504 _state = |
| 498 (_state & ~(_STATE_SUBSCRIBED | _STATE_ADDSTREAM)) | _STATE_CANCELED; | 505 (_state & ~(_STATE_SUBSCRIBED | _STATE_ADDSTREAM)) | _STATE_CANCELED; |
| 499 | 506 |
| 507 if (_onCancel != null) { |
| 508 if (result == null) { |
| 509 // Only introduce a future if one is needed. |
| 510 // If _onCancel returns null, no future is needed. |
| 511 try { |
| 512 result = _onCancel(); |
| 513 } catch (e, s) { |
| 514 // Return the error in the returned future. |
| 515 // Complete it asynchronously, so there is time for a listener |
| 516 // to handle the error. |
| 517 result = new _Future().._asyncCompleteError(e, s); |
| 518 } |
| 519 } else { |
| 520 // Simpler case when we already know that we will return a future. |
| 521 result = result.whenComplete(_onCancel); |
| 522 } |
| 523 } |
| 524 |
| 500 void complete() { | 525 void complete() { |
| 501 if (_doneFuture != null && _doneFuture._mayComplete) { | 526 if (_doneFuture != null && _doneFuture._mayComplete) { |
| 502 _doneFuture._asyncComplete(null); | 527 _doneFuture._asyncComplete(null); |
| 503 } | 528 } |
| 504 } | 529 } |
| 505 | 530 |
| 506 Future future = _runGuarded(_onCancel); | 531 if (result != null) { |
| 507 if (future != null) { | 532 result = result.whenComplete(complete); |
| 508 future = future.whenComplete(complete); | |
| 509 } else { | 533 } else { |
| 510 complete(); | 534 complete(); |
| 511 } | 535 } |
| 512 return future; | 536 |
| 537 return result; |
| 513 } | 538 } |
| 514 | 539 |
| 515 void _recordPause(StreamSubscription<T> subscription) { | 540 void _recordPause(StreamSubscription<T> subscription) { |
| 516 if (_isAddingStream) { | 541 if (_isAddingStream) { |
| 517 _StreamControllerAddStreamState addState = _varData; | 542 _StreamControllerAddStreamState addState = _varData; |
| 518 addState.pause(); | 543 addState.pause(); |
| 519 } | 544 } |
| 520 _runGuarded(_onPause); | 545 _runGuarded(_onPause); |
| 521 } | 546 } |
| 522 | 547 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 }; | 721 }; |
| 697 | 722 |
| 698 void pause() { | 723 void pause() { |
| 699 addSubscription.pause(); | 724 addSubscription.pause(); |
| 700 } | 725 } |
| 701 | 726 |
| 702 void resume() { | 727 void resume() { |
| 703 addSubscription.resume(); | 728 addSubscription.resume(); |
| 704 } | 729 } |
| 705 | 730 |
| 706 void cancel() { | 731 /** |
| 707 addSubscription.cancel(); | 732 * Stop adding the stream. |
| 708 complete(); | 733 * |
| 734 * Complete the future returned by `StreamController.addStream` when |
| 735 * the cancel is complete. |
| 736 * |
| 737 * Return a future if the cancel takes time, otherwise return `null`. |
| 738 */ |
| 739 Future cancel() { |
| 740 var cancel = addSubscription.cancel(); |
| 741 if (cancel == null) { |
| 742 addStreamFuture._asyncComplete(null); |
| 743 return null; |
| 744 } |
| 745 return cancel.whenComplete(() { addStreamFuture._asyncComplete(null); }); |
| 709 } | 746 } |
| 710 | 747 |
| 711 void complete() { | 748 void complete() { |
| 712 addStreamFuture._asyncComplete(null); | 749 addStreamFuture._asyncComplete(null); |
| 713 } | 750 } |
| 714 } | 751 } |
| 715 | 752 |
| 716 class _StreamControllerAddStreamState<T> extends _AddStreamState<T> { | 753 class _StreamControllerAddStreamState<T> extends _AddStreamState<T> { |
| 717 // The subscription or pending data of a _StreamController. | 754 // The subscription or pending data of a _StreamController. |
| 718 // Stored here because we reuse the `_varData` field in the _StreamController | 755 // Stored here because we reuse the `_varData` field in the _StreamController |
| 719 // to store this state object. | 756 // to store this state object. |
| 720 var varData; | 757 var varData; |
| 721 | 758 |
| 722 _StreamControllerAddStreamState(_StreamController controller, | 759 _StreamControllerAddStreamState(_StreamController controller, |
| 723 this.varData, | 760 this.varData, |
| 724 Stream source, | 761 Stream source, |
| 725 bool cancelOnError) | 762 bool cancelOnError) |
| 726 : super(controller, source, cancelOnError) { | 763 : super(controller, source, cancelOnError) { |
| 727 if (controller.isPaused) { | 764 if (controller.isPaused) { |
| 728 addSubscription.pause(); | 765 addSubscription.pause(); |
| 729 } | 766 } |
| 730 } | 767 } |
| 731 } | 768 } |
| OLD | NEW |