Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 import "dart:math"; | 5 import "dart:math"; |
| 6 import "dart:typed_data"; | 6 import "dart:typed_data"; |
| 7 | 7 |
| 8 // Equivalent of calling FATAL from C++ code. | 8 // Equivalent of calling FATAL from C++ code. |
| 9 _fatal(msg) native "DartCore_fatal"; | 9 _fatal(msg) native "DartCore_fatal"; |
| 10 | 10 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 | 29 |
| 30 | 30 |
| 31 // _AsyncStarStreamController is used by the compiler to implement | 31 // _AsyncStarStreamController is used by the compiler to implement |
| 32 // async* generator functions. | 32 // async* generator functions. |
| 33 class _AsyncStarStreamController { | 33 class _AsyncStarStreamController { |
| 34 StreamController controller; | 34 StreamController controller; |
| 35 Function asyncStarBody; | 35 Function asyncStarBody; |
| 36 bool isAdding = false; | 36 bool isAdding = false; |
| 37 bool onListenReceived = false; | 37 bool onListenReceived = false; |
| 38 bool isScheduled = false; | 38 bool isScheduled = false; |
| 39 bool isSuspendedAtYield = false; | |
| 39 Completer cancellationCompleter = null; | 40 Completer cancellationCompleter = null; |
| 40 | 41 |
| 41 Stream get stream => controller.stream; | 42 Stream get stream => controller.stream; |
| 42 | 43 |
| 43 void runBody() { | 44 void runBody() { |
| 44 isScheduled = false; | 45 isScheduled = false; |
| 46 isSuspendedAtYield = false; | |
|
Lasse Reichstein Nielsen
2015/04/09 06:35:30
If I understand this correctly, your possible stat
hausner
2015/04/09 17:10:19
I agree that the code and comments could be cleare
| |
| 45 asyncStarBody(); | 47 asyncStarBody(); |
| 46 } | 48 } |
| 47 | 49 |
| 48 void scheduleGenerator() { | 50 void scheduleGenerator() { |
| 49 if (isScheduled || controller.isPaused || isAdding) { | 51 if (isScheduled || controller.isPaused || isAdding) { |
| 50 return; | 52 return; |
| 51 } | 53 } |
| 52 isScheduled = true; | 54 isScheduled = true; |
| 53 scheduleMicrotask(runBody); | 55 scheduleMicrotask(runBody); |
| 54 } | 56 } |
| 55 | 57 |
| 56 // Adds element to steam, returns true if the caller should terminate | 58 // Adds element to steam, returns true if the caller should terminate |
| 57 // execution of the generator. | 59 // execution of the generator. |
| 58 // | 60 // |
| 59 // TODO(hausner): Per spec, the generator should be suspended before | 61 // TODO(hausner): Per spec, the generator should be suspended before |
| 60 // exiting when the stream is closed. We could add a getter like this: | 62 // exiting when the stream is closed. We could add a getter like this: |
| 61 // get isCancelled => controller.hasListener; | 63 // get isCancelled => controller.hasListener; |
| 62 // The generator would translate a 'yield e' statement to | 64 // The generator would translate a 'yield e' statement to |
| 63 // controller.add(e); | 65 // controller.add(e); |
| 64 // suspend; | 66 // suspend; |
| 65 // if (controller.isCanelled) return; | 67 // if (controller.isCancelled) return; |
| 66 bool add(event) { | 68 bool add(event) { |
| 67 if (!onListenReceived) _fatal("yield before stream is listened to!"); | 69 if (!onListenReceived) _fatal("yield before stream is listened to!"); |
| 70 if (isSuspendedAtYield) _fatal("unexpected yield"); | |
| 68 // If stream is cancelled, tell caller to exit the async generator. | 71 // If stream is cancelled, tell caller to exit the async generator. |
| 69 if (!controller.hasListener) { | 72 if (!controller.hasListener) { |
| 70 return true; | 73 return true; |
| 71 } | 74 } |
| 72 controller.add(event); | 75 controller.add(event); |
| 73 scheduleGenerator(); | 76 scheduleGenerator(); |
| 77 isSuspendedAtYield = true; | |
| 74 return false; | 78 return false; |
| 75 } | 79 } |
| 76 | 80 |
| 77 // Adds the elements of stream into this controller's stream. | 81 // Adds the elements of stream into this controller's stream. |
| 78 // The generator will be scheduled again when all of the | 82 // The generator will be scheduled again when all of the |
| 79 // elements of the added stream have been consumed. | 83 // elements of the added stream have been consumed. |
| 80 // Returns true if the caller should terminate | 84 // Returns true if the caller should terminate |
| 81 // execution of the generator. | 85 // execution of the generator. |
| 82 bool addStream(Stream stream) { | 86 bool addStream(Stream stream) { |
| 83 if (!onListenReceived) _fatal("yield before stream is listened to!"); | 87 if (!onListenReceived) _fatal("yield before stream is listened to!"); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 onCancel: this.onCancel); | 128 onCancel: this.onCancel); |
| 125 } | 129 } |
| 126 | 130 |
| 127 onListen() { | 131 onListen() { |
| 128 assert(!onListenReceived); | 132 assert(!onListenReceived); |
| 129 onListenReceived = true; | 133 onListenReceived = true; |
| 130 scheduleGenerator(); | 134 scheduleGenerator(); |
| 131 } | 135 } |
| 132 | 136 |
| 133 onResume() { | 137 onResume() { |
| 134 scheduleGenerator(); | 138 if (isSuspendedAtYield) { |
| 139 scheduleGenerator(); | |
| 140 } | |
| 135 } | 141 } |
| 136 | 142 |
| 137 onCancel() { | 143 onCancel() { |
| 138 if (controller.isClosed) { | 144 if (controller.isClosed) { |
| 139 return null; | 145 return null; |
| 140 } | 146 } |
| 141 if (cancellationCompleter == null) { | 147 if (cancellationCompleter == null) { |
| 142 cancellationCompleter = new Completer(); | 148 cancellationCompleter = new Completer(); |
| 143 scheduleGenerator(); | 149 scheduleGenerator(); |
| 144 } | 150 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 if (isYieldEach) { | 199 if (isYieldEach) { |
| 194 // Spec mandates: it is a dynamic error if the class of [the object | 200 // Spec mandates: it is a dynamic error if the class of [the object |
| 195 // returned by yield*] does not implement Iterable. | 201 // returned by yield*] does not implement Iterable. |
| 196 yieldEachIterator = (current as Iterable).iterator; | 202 yieldEachIterator = (current as Iterable).iterator; |
| 197 continue; | 203 continue; |
| 198 } | 204 } |
| 199 return true; | 205 return true; |
| 200 } | 206 } |
| 201 } | 207 } |
| 202 } | 208 } |
| OLD | NEW |