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

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

Issue 23926011: Rewrite Futures. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Remove chained future cycle test. Created 7 years, 3 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 /** 7 /**
8 * A [Future] represents a delayed computation. It is used to obtain a not-yet 8 * A [Future] represents a delayed computation. It is used to obtain a not-yet
9 * available value, or error, sometime in the future. Receivers of a 9 * available value, or error, sometime in the future. Receivers of a
10 * [Future] can register callbacks that handle the value or error once it is 10 * [Future] can register callbacks that handle the value or error once it is
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 * completed with the error. If a thrown value is an [AsyncError], it is used 93 * completed with the error. If a thrown value is an [AsyncError], it is used
94 * directly, instead of wrapping this error again in another [AsyncError]. 94 * directly, instead of wrapping this error again in another [AsyncError].
95 * 95 *
96 * If the returned value is itself a [Future], completion of 96 * If the returned value is itself a [Future], completion of
97 * the created future will wait until the returned future completes, 97 * the created future will wait until the returned future completes,
98 * and will then complete with the same result. 98 * and will then complete with the same result.
99 * 99 *
100 * If a value is returned, it becomes the result of the created future. 100 * If a value is returned, it becomes the result of the created future.
101 */ 101 */
102 factory Future(computation()) { 102 factory Future(computation()) {
103 _ThenFuture<dynamic, T> future = 103 Completer completer = new Completer.sync();
Lasse Reichstein Nielsen 2013/09/10 12:03:53 WHy not "new _Future()" followed by ".complete" or
floitsch 2013/09/10 17:19:14 Done.
104 new _ThenFuture<dynamic, T>((_) => computation()); 104 Timer.run(() {
105 Timer.run(() => future._sendValue(null)); 105 try {
106 return future; 106 completer.complete(computation());
107 } catch (e, s) {
108 completer.completeError(e, s);
109 }
110 });
111 return completer.future;
107 } 112 }
108 113
109 /** 114 /**
110 * Creates a future containing the result of immediately calling 115 * Creates a future containing the result of immediately calling
111 * [computation]. 116 * [computation].
112 * 117 *
113 * if the result of executing [computation] throws, the returned future is 118 * if the result of executing [computation] throws, the returned future is
Lasse Reichstein Nielsen 2013/09/10 12:03:53 Capital "I". And reword to "If calling [computatio
floitsch 2013/09/10 17:19:14 Done.
114 * completed with the error. If a thrown value is an [AsyncError], it is used 119 * completed with the error. If a thrown value is an [AsyncError], it is used
115 * directly, instead of wrapping this error again in another [AsyncError]. 120 * directly, instead of wrapping this error again in another [AsyncError].
116 * 121 *
117 * If the returned value is itself a [Future], completion of 122 * If the returned value is itself a [Future], completion of
118 * the created future will wait until the returned future completes, 123 * the created future will wait until the returned future completes,
119 * and will then complete with the same result. 124 * and will then complete with the same result.
120 */ 125 */
121 factory Future.sync(computation()) { 126 factory Future.sync(computation()) {
122 try { 127 try {
123 var result = computation(); 128 var result = computation();
124 return new _FutureImpl<T>().._setOrChainValue(result); 129 return new Future.value(result);
125 } catch (error, stackTrace) { 130 } catch (error, stackTrace) {
126 return new _FutureImpl<T>.immediateError(error, stackTrace); 131 return new Future.error(error, stackTrace);
127 } 132 }
128 } 133 }
129 134
130 /** 135 /**
131 * A future whose value is available in the next event-loop iteration. 136 * A future whose value is available in the next event-loop iteration.
132 * 137 *
133 * If [value] is not a [Future], using this constructor is equivalent 138 * If [value] is not a [Future], using this constructor is equivalent
134 * to [:new Future.sync(() => value):]. 139 * to [:new Future.sync(() => value):].
135 * 140 *
136 * See [Completer] to create a Future and complete it later. 141 * See [Completer] to create a Future and complete it later.
137 */ 142 */
138 factory Future.value([T value]) => new _FutureImpl<T>.immediate(value); 143 factory Future.value([T value]) {
144 return new _Future<T>.immediate(value);
145 }
139 146
140 /** 147 /**
141 * A future that completes with an error in the next event-loop iteration. 148 * A future that completes with an error in the next event-loop iteration.
142 * 149 *
143 * See [Completer] to create a Future and complete it later. 150 * See [Completer] to create a Future and complete it later.
144 */ 151 */
145 factory Future.error(var error, [Object stackTrace]) { 152 factory Future.error(var error, [Object stackTrace]) {
146 return new _FutureImpl<T>.immediateError(error, stackTrace); 153 return new _Future<T>.immediateError(error, stackTrace);
147 } 154 }
148 155
149 /** 156 /**
150 * Creates a future that completes after a delay. 157 * Creates a future that completes after a delay.
151 * 158 *
152 * The future will be completed after the given [duration] has passed with 159 * The future will be completed after the given [duration] has passed with
153 * the result of calling [computation]. If the duration is 0 or less, it 160 * the result of calling [computation]. If the duration is 0 or less, it
154 * completes no sooner than in the next event-loop iteration. 161 * completes no sooner than in the next event-loop iteration.
155 * 162 *
156 * If [computation] is not given or [:null:] then it will behave as if 163 * If [computation] is not given or [:null:] then it will behave as if
157 * [computation] was set to [:() => null:]. That is, it will complete with 164 * [computation] was set to [:() => null:]. That is, it will complete with
158 * [:null:]. 165 * [:null:].
159 * 166 *
160 * If calling [computation] throws, the created future will complete with the 167 * If calling [computation] throws, the created future will complete with the
161 * error. 168 * error.
162 * 169 *
163 * See [Completer]s, for futures with values that are computed asynchronously. 170 * See [Completer]s, for futures with values that are computed asynchronously.
164 */ 171 */
165 factory Future.delayed(Duration duration, [T computation()]) { 172 factory Future.delayed(Duration duration, [T computation()]) {
166 // TODO(floitsch): no need to allocate a ThenFuture when the computation is 173 Completer completer = new Completer.sync();
167 // null. 174 Future result = completer.future;
168 if (computation == null) computation = (() => null); 175 if (computation != null) {
169 _ThenFuture<dynamic, T> future = 176 result = result.then((ignored) => computation());
Lasse Reichstein Nielsen 2013/09/10 12:03:53 This throws away the type parameter. Can we avoid
floitsch 2013/09/10 17:19:14 Not now. We will go through the whole library and
170 new _ThenFuture<dynamic, T>((_) => computation()); 177 }
171 new Timer(duration, () => future._sendValue(null)); 178 new Timer(duration, () { completer.complete(null); });
172 return future; 179 return result;
173 } 180 }
174 181
175 /** 182 /**
176 * Wait for all the given futures to complete and collect their values. 183 * Wait for all the given futures to complete and collect their values.
177 * 184 *
178 * Returns a future which will complete once all the futures in a list are 185 * Returns a future which will complete once all the futures in a list are
179 * complete. If any of the futures in the list completes with an error, 186 * complete. If any of the futures in the list completes with an error,
180 * the resulting future also completes with an error. Otherwise the value 187 * the resulting future also completes with an error. Otherwise the value
181 * of the returned future will be a list of all the values that were produced. 188 * of the returned future will be a list of all the values that were produced.
182 */ 189 */
183 static Future<List> wait(Iterable<Future> futures) { 190 static Future<List> wait(Iterable<Future> futures) {
184 return new _FutureImpl<List>.wait(futures); 191 Completer completer;
192 // List collecting values from the futures.
193 // Set to null if an error occurs.
194 List values;
195 void handleError(error) {
196 if (values != null) {
197 values = null;
198 completer.completeError(error);
199 }
200 }
201 // As each future completes, put its value into the corresponding
202 // position in the list of values.
203 int remaining = 0;
204 for (Future future in futures) {
205 int pos = remaining++;
206 future.catchError(handleError).then((Object value) {
207 if (values == null) return null;
208 values[pos] = value;
209 remaining--;
210 if (remaining == 0) {
211 completer.complete(values);
212 }
213 });
214 }
215 if (remaining == 0) {
216 return new Future.value(const []);
217 }
218 values = new List(remaining);
219 completer = new Completer<List>();
220 return completer.future;
185 } 221 }
186 222
187 /** 223 /**
188 * Perform an async operation for each element of the iterable, in turn. 224 * Perform an async operation for each element of the iterable, in turn.
189 * 225 *
190 * Runs [f] for each element in [input] in order, moving to the next element 226 * Runs [f] for each element in [input] in order, moving to the next element
191 * only when the [Future] returned by [f] completes. Returns a [Future] that 227 * only when the [Future] returned by [f] completes. Returns a [Future] that
192 * completes when all elements have been processed. 228 * completes when all elements have been processed.
193 * 229 *
194 * The return values of all [Future]s are discarded. Any errors will cause the 230 * The return values of all [Future]s are discarded. Any errors will cause the
195 * iteration to stop and will be piped through the returned [Future]. 231 * iteration to stop and will be piped through the returned [Future].
196 */ 232 */
197 static Future forEach(Iterable input, Future f(element)) { 233 static Future forEach(Iterable input, Future f(element)) {
198 _FutureImpl doneSignal = new _FutureImpl(); 234 _Future doneSignal = new _Future();
199 Iterator iterator = input.iterator; 235 Iterator iterator = input.iterator;
200 void nextElement(_) { 236 void nextElement(_) {
201 if (iterator.moveNext()) { 237 if (iterator.moveNext()) {
202 new Future.sync(() => f(iterator.current)) 238 new Future.sync(() => f(iterator.current))
203 .then(nextElement, onError: doneSignal._setError); 239 .then(nextElement, onError: doneSignal._completeError);
204 } else { 240 } else {
205 doneSignal._setValue(null); 241 doneSignal._complete(null);
206 } 242 }
207 } 243 }
208 nextElement(null); 244 nextElement(null);
209 return doneSignal; 245 return doneSignal;
210 } 246 }
211 247
212 /** 248 /**
213 * When this future completes with a value, then [onValue] is called with this 249 * When this future completes with a value, then [onValue] is called with this
214 * value. If [this] future is already completed then the invocation of 250 * value. If [this] future is already completed then the invocation of
215 * [onValue] is delayed until the next event-loop iteration. 251 * [onValue] is delayed until the next event-loop iteration.
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 * 454 *
419 * The argument [exception] must not be `null`. 455 * The argument [exception] must not be `null`.
420 */ 456 */
421 void completeError(Object exception, [Object stackTrace]); 457 void completeError(Object exception, [Object stackTrace]);
422 458
423 /** 459 /**
424 * Whether the future has been completed. 460 * Whether the future has been completed.
425 */ 461 */
426 bool get isCompleted; 462 bool get isCompleted;
427 } 463 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698