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

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

Issue 11783009: Big merge from experimental to bleeding edge. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 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
« no previous file with comments | « sdk/lib/core/expect.dart ('k') | sdk/lib/core/future_impl.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart.core;
6
7 /**
8 * A [Future] is used to obtain a value sometime in the future. Receivers of a
9 * [Future] can obtain the value by passing a callback to [then]. For example:
10 *
11 * Future<int> future = getFutureFromSomewhere();
12 * future.then((value) {
13 * print("I received the number $value");
14 * });
15 *
16 * A future may complete by *succeeding* (producing a value) or *failing*
17 * (producing an exception, which may be handled with [handleException]).
18 * Callbacks passed to [onComplete] will be invoked in either case.
19 *
20 * When a future completes, the following actions happen in order:
21 *
22 * 1. if the future suceeded, handlers registered with [then] are called.
23 * 2. if the future failed, handlers registered with [handleException] are
24 * called in sequence, until one returns true.
25 * 3. handlers registered with [onComplete] are called
26 * 4. if the future failed, and at least one handler was registered with
27 * [then], and no handler registered with [handleException] returned
28 * [:true:], then the exception is thrown.
29 *
30 * Use a [Completer] to create and change the state of a [Future].
31 */
32 abstract class Future<T> {
33 /** A future whose value is immediately available. */
34 factory Future.immediate(T value) => new _FutureImpl<T>.immediate(value);
35
36 /** The value provided. Throws an exception if [hasValue] is false. */
37 T get value;
38
39 /**
40 * Exception that occurred ([:null:] if no exception occured). This property
41 * throws a [FutureNotCompleteException] if it is used before this future is
42 * completes.
43 */
44 Object get exception;
45
46 /**
47 * The stack trace object associated with the exception that occurred. This
48 * throws a [FutureNotCompleteException] if it is used before the future
49 * completes. Returns [:null:] if the future completed successfully or a
50 * stack trace wasn't provided with the exception when it occurred.
51 */
52 Object get stackTrace;
53
54 /**
55 * Whether the future is complete (either the value is available or there was
56 * an exception).
57 */
58 bool get isComplete;
59
60 /**
61 * Whether the value is available (meaning [isComplete] is true, and there was
62 * no exception).
63 */
64 bool get hasValue;
65
66 /**
67 * When this future is complete (either with a value or with an exception),
68 * then [complete] is called with the future.
69 * If [complete] throws an exception, it is ignored.
70 */
71 void onComplete(void complete(Future<T> future));
72
73 /**
74 * If this future is complete and has a value, then [onSuccess] is called
75 * with the value.
76 */
77 void then(void onSuccess(T value));
78
79 /**
80 * If this future is complete and has an exception, then call [onException].
81 *
82 * If [onException] returns true, then the exception is considered handled.
83 *
84 * If [onException] does not return true (or [handleException] was never
85 * called), then the exception is not considered handled. In that case, if
86 * there were any calls to [then], then the exception will be thrown when the
87 * value is set.
88 *
89 * In most cases it should not be necessary to call [handleException],
90 * because the exception associated with this [Future] will propagate
91 * naturally if the future's value is being consumed. Only call
92 * [handleException] if you need to do some special local exception handling
93 * related to this particular Future's value.
94 */
95 void handleException(bool onException(Object exception));
96
97 /**
98 * A future representing [transformation] applied to this future's value.
99 *
100 * When this future gets a value, [transformation] will be called on the
101 * value, and the returned future will receive the result.
102 *
103 * If an exception occurs (received by this future, or thrown by
104 * [transformation]) then the returned future will receive the exception.
105 *
106 * You must not add exception handlers to [this] future prior to calling
107 * transform, and any you add afterwards will not be invoked.
108 */
109 Future transform(transformation(T value));
110
111 /**
112 * A future representing an asynchronous transformation applied to this
113 * future's value. [transformation] must return a Future.
114 *
115 * When this future gets a value, [transformation] will be called on the
116 * value. When the resulting future gets a value, the returned future
117 * will receive it.
118 *
119 * If an exception occurs (received by this future, thrown by
120 * [transformation], or received by the future returned by [transformation])
121 * then the returned future will receive the exception.
122 *
123 * You must not add exception handlers to [this] future prior to calling
124 * chain, and any you add afterwards will not be invoked.
125 */
126 Future chain(Future transformation(T value));
127
128 /**
129 * A future representing [transformation] applied to this future's exception.
130 * This can be used to "catch" an exception coming from `this` and translate
131 * it to a more appropriate result.
132 *
133 * If this future gets a value, it simply completes to that same value. If an
134 * exception occurs, then [transformation] will be called with the exception
135 * value. If [transformation] itself throws an exception, then the returned
136 * future completes with that exception. Otherwise, the future will complete
137 * with the value returned by [transformation]. If the returned value is
138 * itself a future, then the future returned by [transformException] will
139 * complete with the value that that future completes to.
140 */
141 Future transformException(transformation(Object exception));
142 }
143
144 /**
145 * A [Completer] is used to produce [Future]s and supply their value when it
146 * becomes available.
147 *
148 * A service that provides values to callers, and wants to return [Future]s can
149 * use a [Completer] as follows:
150 *
151 * Completer completer = new Completer();
152 * // send future object back to client...
153 * return completer.future;
154 * ...
155 *
156 * // later when value is available, call:
157 * completer.complete(value);
158 *
159 * // alternatively, if the service cannot produce the value, it
160 * // can provide an exception:
161 * completer.completeException(exception);
162 *
163 */
164 abstract class Completer<T> {
165
166 factory Completer() => new _CompleterImpl<T>();
167
168 /** The future that will contain the value produced by this completer. */
169 Future get future;
170
171 /** Supply a value for [future]. */
172 void complete(T value);
173
174 /**
175 * Indicate in [future] that an exception occured while trying to produce its
176 * value. The argument [exception] should not be [:null:]. A [stackTrace]
177 * object can be provided as well to give the user information about where
178 * the error occurred. If omitted, it will be [:null:].
179 */
180 void completeException(Object exception, [Object stackTrace]);
181 }
182
183 /** Thrown when reading a future's properties before it is complete. */
184 class FutureNotCompleteException implements Exception {
185 FutureNotCompleteException() {}
186 String toString() => "Exception: future has not been completed";
187 }
188
189 /**
190 * Thrown if a completer tries to set the value on a future that is already
191 * complete.
192 */
193 class FutureAlreadyCompleteException implements Exception {
194 FutureAlreadyCompleteException() {}
195 String toString() => "Exception: future already completed";
196 }
197
198 /**
199 * Wraps unhandled exceptions provided to [Completer.completeException]. It is
200 * used to show both the error message and the stack trace for unhandled
201 * exceptions.
202 */
203 class FutureUnhandledException implements Exception {
204 /** Wrapped exception. */
205 var source;
206
207 /** Trace for the wrapped exception. */
208 Object stackTrace;
209
210 FutureUnhandledException(this.source, this.stackTrace);
211
212 String toString() {
213 return 'FutureUnhandledException: exception while executing Future\n '
214 '${source.toString().replaceAll("\n", "\n ")}\n'
215 'original stack trace:\n '
216 '${stackTrace.toString().replaceAll("\n","\n ")}';
217 }
218 }
219
220
221 /**
222 * [Futures] holds additional utility functions that operate on [Future]s (for
223 * example, waiting for a collection of Futures to complete).
224 */
225 class Futures {
226 /**
227 * Returns a future which will complete once all the futures in a list are
228 * complete. If any of the futures in the list completes with an exception,
229 * the resulting future also completes with an exception. (The value of the
230 * returned future will be a list of all the values that were produced.)
231 */
232 static Future<List> wait(List<Future> futures) {
233 if (futures.isEmpty) {
234 return new Future<List>.immediate(const []);
235 }
236
237 Completer completer = new Completer<List>();
238 Future<List> result = completer.future;
239 int remaining = futures.length;
240 List values = new List(futures.length);
241
242 // As each future completes, put its value into the corresponding
243 // position in the list of values.
244 for (int i = 0; i < futures.length; i++) {
245 // TODO(mattsh) - remove this after bug
246 // http://code.google.com/p/dart/issues/detail?id=333 is fixed.
247 int pos = i;
248 Future future = futures[pos];
249 future.then((Object value) {
250 values[pos] = value;
251 if (--remaining == 0 && !result.isComplete) {
252 completer.complete(values);
253 }
254 });
255 future.handleException((exception) {
256 if (!result.isComplete) {
257 completer.completeException(exception, future.stackTrace);
258 }
259 return true;
260 });
261 }
262 return result;
263 }
264
265 /**
266 * Runs [f] for each element in [input] in order, moving to the next element
267 * only when the [Future] returned by [f] completes. Returns a [Future] that
268 * completes when all elements have been processed.
269 *
270 * The return values of all [Future]s are discarded. Any errors will cause the
271 * iteration to stop and will be piped through the returned [Future].
272 */
273 static Future forEach(Iterable input, Future f(element)) {
274 var iterator = input.iterator();
275 Future nextElement(_) {
276 if (!iterator.hasNext) return new Future.immediate(null);
277 return f(iterator.next()).chain(nextElement);
278 }
279 return nextElement(null);
280 }
281 }
OLDNEW
« no previous file with comments | « sdk/lib/core/expect.dart ('k') | sdk/lib/core/future_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698