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

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

Issue 2754013002: Format all dart: library files (Closed)
Patch Set: Format all dart: library files Created 3 years, 9 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
« no previous file with comments | « sdk/lib/async/future.dart ('k') | sdk/lib/async/schedule_microtask.dart » ('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 /** The onValue and onError handlers return either a value or a future */ 7 /** The onValue and onError handlers return either a value or a future */
8 typedef FutureOr<T> _FutureOnValue<S, T>(S value); 8 typedef FutureOr<T> _FutureOnValue<S, T>(S value);
9 /** Test used by [Future.catchError] to handle skip some errors. */ 9 /** Test used by [Future.catchError] to handle skip some errors. */
10 typedef bool _FutureErrorTest(var error); 10 typedef bool _FutureErrorTest(var error);
(...skipping 17 matching lines...) Expand all
28 } 28 }
29 29
30 void _completeError(Object error, StackTrace stackTrace); 30 void _completeError(Object error, StackTrace stackTrace);
31 31
32 // The future's _isComplete doesn't take into account pending completions. 32 // The future's _isComplete doesn't take into account pending completions.
33 // We therefore use _mayComplete. 33 // We therefore use _mayComplete.
34 bool get isCompleted => !future._mayComplete; 34 bool get isCompleted => !future._mayComplete;
35 } 35 }
36 36
37 class _AsyncCompleter<T> extends _Completer<T> { 37 class _AsyncCompleter<T> extends _Completer<T> {
38
39 void complete([FutureOr<T> value]) { 38 void complete([FutureOr<T> value]) {
40 if (!future._mayComplete) throw new StateError("Future already completed"); 39 if (!future._mayComplete) throw new StateError("Future already completed");
41 future._asyncComplete(value); 40 future._asyncComplete(value);
42 } 41 }
43 42
44 void _completeError(Object error, StackTrace stackTrace) { 43 void _completeError(Object error, StackTrace stackTrace) {
45 future._asyncCompleteError(error, stackTrace); 44 future._asyncCompleteError(error, stackTrace);
46 } 45 }
47 } 46 }
48 47
49 class _SyncCompleter<T> extends _Completer<T> { 48 class _SyncCompleter<T> extends _Completer<T> {
50 void complete([FutureOr<T> value]) { 49 void complete([FutureOr<T> value]) {
51 if (!future._mayComplete) throw new StateError("Future already completed"); 50 if (!future._mayComplete) throw new StateError("Future already completed");
52 future._complete(value); 51 future._complete(value);
53 } 52 }
54 53
55 void _completeError(Object error, StackTrace stackTrace) { 54 void _completeError(Object error, StackTrace stackTrace) {
56 future._completeError(error, stackTrace); 55 future._completeError(error, stackTrace);
57 } 56 }
58 } 57 }
59 58
60 class _FutureListener<S, T> { 59 class _FutureListener<S, T> {
61 static const int MASK_VALUE = 1; 60 static const int MASK_VALUE = 1;
62 static const int MASK_ERROR = 2; 61 static const int MASK_ERROR = 2;
63 static const int MASK_TEST_ERROR = 4; 62 static const int MASK_TEST_ERROR = 4;
64 static const int MASK_WHENCOMPLETE = 8; 63 static const int MASK_WHENCOMPLETE = 8;
65 static const int STATE_CHAIN = 0; 64 static const int STATE_CHAIN = 0;
66 static const int STATE_THEN = MASK_VALUE; 65 static const int STATE_THEN = MASK_VALUE;
67 // TODO(johnmccutchan): Remove the hard coded value. See #26030. 66 // TODO(johnmccutchan): Remove the hard coded value. See #26030.
68 static const int STATE_THEN_ONERROR = 3; // MASK_VALUE | MASK_ERROR. 67 static const int STATE_THEN_ONERROR = 3; // MASK_VALUE | MASK_ERROR.
69 static const int STATE_CATCHERROR = MASK_ERROR; 68 static const int STATE_CATCHERROR = MASK_ERROR;
70 // TODO(johnmccutchan): Remove the hard coded value. See #26030. 69 // TODO(johnmccutchan): Remove the hard coded value. See #26030.
71 static const int STATE_CATCHERROR_TEST = 6; // MASK_ERROR | MASK_TEST_ERROR. 70 static const int STATE_CATCHERROR_TEST = 6; // MASK_ERROR | MASK_TEST_ERROR.
72 static const int STATE_WHENCOMPLETE = MASK_WHENCOMPLETE; 71 static const int STATE_WHENCOMPLETE = MASK_WHENCOMPLETE;
73 // Listeners on the same future are linked through this link. 72 // Listeners on the same future are linked through this link.
74 _FutureListener _nextListener = null; 73 _FutureListener _nextListener = null;
75 // The future to complete when this listener is activated. 74 // The future to complete when this listener is activated.
76 final _Future<T> result; 75 final _Future<T> result;
77 // Which fields means what. 76 // Which fields means what.
78 final int state; 77 final int state;
79 // Used for then/whenDone callback and error test 78 // Used for then/whenDone callback and error test
80 final Function callback; 79 final Function callback;
81 // Used for error callbacks. 80 // Used for error callbacks.
82 final Function errorCallback; 81 final Function errorCallback;
83 82
84 _FutureListener.then(this.result, 83 _FutureListener.then(
85 _FutureOnValue<S, T> onValue, Function errorCallback) 84 this.result, _FutureOnValue<S, T> onValue, Function errorCallback)
86 : callback = onValue, 85 : callback = onValue,
87 errorCallback = errorCallback, 86 errorCallback = errorCallback,
88 state = (errorCallback == null) ? STATE_THEN : STATE_THEN_ONERROR; 87 state = (errorCallback == null) ? STATE_THEN : STATE_THEN_ONERROR;
89 88
90 _FutureListener.catchError(this.result, 89 _FutureListener.catchError(
91 this.errorCallback, _FutureErrorTest test) 90 this.result, this.errorCallback, _FutureErrorTest test)
92 : callback = test, 91 : callback = test,
93 state = (test == null) ? STATE_CATCHERROR : STATE_CATCHERROR_TEST; 92 state = (test == null) ? STATE_CATCHERROR : STATE_CATCHERROR_TEST;
94 93
95 _FutureListener.whenComplete(this.result, _FutureAction onComplete) 94 _FutureListener.whenComplete(this.result, _FutureAction onComplete)
96 : callback = onComplete, 95 : callback = onComplete,
97 errorCallback = null, 96 errorCallback = null,
98 state = STATE_WHENCOMPLETE; 97 state = STATE_WHENCOMPLETE;
99 98
100 Zone get _zone => result._zone; 99 Zone get _zone => result._zone;
101 100
102 bool get handlesValue => (state & MASK_VALUE != 0); 101 bool get handlesValue => (state & MASK_VALUE != 0);
103 bool get handlesError => (state & MASK_ERROR != 0); 102 bool get handlesError => (state & MASK_ERROR != 0);
104 bool get hasErrorTest => (state == STATE_CATCHERROR_TEST); 103 bool get hasErrorTest => (state == STATE_CATCHERROR_TEST);
105 bool get handlesComplete => (state == STATE_WHENCOMPLETE); 104 bool get handlesComplete => (state == STATE_WHENCOMPLETE);
106 105
107
108 _FutureOnValue<S, T> get _onValue { 106 _FutureOnValue<S, T> get _onValue {
109 assert(handlesValue); 107 assert(handlesValue);
110 return callback as Object /*=_FutureOnValue<S, T>*/; 108 return callback as Object/*=_FutureOnValue<S, T>*/;
111 } 109 }
110
112 Function get _onError => errorCallback; 111 Function get _onError => errorCallback;
113 _FutureErrorTest get _errorTest { 112 _FutureErrorTest get _errorTest {
114 assert(hasErrorTest); 113 assert(hasErrorTest);
115 return callback as Object /*=_FutureErrorTest*/; 114 return callback as Object/*=_FutureErrorTest*/;
116 } 115 }
116
117 _FutureAction get _whenCompleteAction { 117 _FutureAction get _whenCompleteAction {
118 assert(handlesComplete); 118 assert(handlesComplete);
119 return callback as Object /*=_FutureAction*/; 119 return callback as Object/*=_FutureAction*/;
120 } 120 }
121 121
122 /// Whether this listener has an error callback. 122 /// Whether this listener has an error callback.
123 /// 123 ///
124 /// This function must only be called if the listener [handlesError]. 124 /// This function must only be called if the listener [handlesError].
125 bool get hasErrorCallback { 125 bool get hasErrorCallback {
126 assert(handlesError); 126 assert(handlesError);
127 return _onError != null; 127 return _onError != null;
128 } 128 }
129 129
130 FutureOr<T> handleValue(S sourceResult) { 130 FutureOr<T> handleValue(S sourceResult) {
131 return _zone.runUnary<FutureOr<T>, S>( 131 return _zone.runUnary<FutureOr<T>, S>(_onValue, sourceResult);
132 _onValue, sourceResult);
133 } 132 }
134 133
135 bool matchesErrorTest(AsyncError asyncError) { 134 bool matchesErrorTest(AsyncError asyncError) {
136 if (!hasErrorTest) return true; 135 if (!hasErrorTest) return true;
137 _FutureErrorTest test = _errorTest; 136 _FutureErrorTest test = _errorTest;
138 return _zone.runUnary<bool, dynamic>(_errorTest, asyncError.error); 137 return _zone.runUnary<bool, dynamic>(_errorTest, asyncError.error);
139 } 138 }
140 139
141 FutureOr<T> handleError(AsyncError asyncError) { 140 FutureOr<T> handleError(AsyncError asyncError) {
142 assert(handlesError && hasErrorCallback); 141 assert(handlesError && hasErrorCallback);
143 if (errorCallback is ZoneBinaryCallback) { 142 if (errorCallback is ZoneBinaryCallback) {
144 var typedErrorCallback = errorCallback as Object 143 var typedErrorCallback = errorCallback as Object
145 /*=ZoneBinaryCallback<FutureOr<T>, Object, StackTrace>*/; 144 /*=ZoneBinaryCallback<FutureOr<T>, Object, StackTrace>*/;
146 return _zone.runBinary(typedErrorCallback, 145 return _zone.runBinary(
147 asyncError.error, 146 typedErrorCallback, asyncError.error, asyncError.stackTrace);
148 asyncError.stackTrace);
149 } else { 147 } else {
150 return _zone.runUnary<FutureOr<T>, dynamic>( 148 return _zone.runUnary<FutureOr<T>, dynamic>(
151 errorCallback, asyncError.error); 149 errorCallback, asyncError.error);
152 } 150 }
153 } 151 }
154 152
155 dynamic handleWhenComplete() { 153 dynamic handleWhenComplete() {
156 assert(!handlesError); 154 assert(!handlesError);
157 return _zone.run(_whenCompleteAction); 155 return _zone.run(_whenCompleteAction);
158 } 156 }
159 } 157 }
160 158
161 class _Future<T> implements Future<T> { 159 class _Future<T> implements Future<T> {
162 /// Initial state, waiting for a result. In this state, the 160 /// Initial state, waiting for a result. In this state, the
163 /// [resultOrListeners] field holds a single-linked list of 161 /// [resultOrListeners] field holds a single-linked list of
164 /// [_FutureListener] listeners. 162 /// [_FutureListener] listeners.
165 static const int _INCOMPLETE = 0; 163 static const int _INCOMPLETE = 0;
164
166 /// Pending completion. Set when completed using [_asyncComplete] or 165 /// Pending completion. Set when completed using [_asyncComplete] or
167 /// [_asyncCompleteError]. It is an error to try to complete it again. 166 /// [_asyncCompleteError]. It is an error to try to complete it again.
168 /// [resultOrListeners] holds listeners. 167 /// [resultOrListeners] holds listeners.
169 static const int _PENDING_COMPLETE = 1; 168 static const int _PENDING_COMPLETE = 1;
169
170 /// The future has been chained to another future. The result of that 170 /// The future has been chained to another future. The result of that
171 /// other future becomes the result of this future as well. 171 /// other future becomes the result of this future as well.
172 /// [resultOrListeners] contains the source future. 172 /// [resultOrListeners] contains the source future.
173 static const int _CHAINED = 2; 173 static const int _CHAINED = 2;
174
174 /// The future has been completed with a value result. 175 /// The future has been completed with a value result.
175 static const int _VALUE = 4; 176 static const int _VALUE = 4;
177
176 /// The future has been completed with an error result. 178 /// The future has been completed with an error result.
177 static const int _ERROR = 8; 179 static const int _ERROR = 8;
178 180
179 /** Whether the future is complete, and as what. */ 181 /** Whether the future is complete, and as what. */
180 int _state = _INCOMPLETE; 182 int _state = _INCOMPLETE;
181 183
182 /** 184 /**
183 * Zone that the future was completed from. 185 * Zone that the future was completed from.
184 * This is the zone that an error result belongs to. 186 * This is the zone that an error result belongs to.
185 * 187 *
(...skipping 24 matching lines...) Expand all
210 212
211 /// Valid types for value: `T` or `Future<T>`. 213 /// Valid types for value: `T` or `Future<T>`.
212 _Future.immediate(value) { 214 _Future.immediate(value) {
213 _asyncComplete(value); 215 _asyncComplete(value);
214 } 216 }
215 217
216 _Future.immediateError(var error, [StackTrace stackTrace]) { 218 _Future.immediateError(var error, [StackTrace stackTrace]) {
217 _asyncCompleteError(error, stackTrace); 219 _asyncCompleteError(error, stackTrace);
218 } 220 }
219 221
220 bool get _mayComplete => _state == _INCOMPLETE; 222 bool get _mayComplete => _state == _INCOMPLETE;
221 bool get _isPendingComplete => _state == _PENDING_COMPLETE; 223 bool get _isPendingComplete => _state == _PENDING_COMPLETE;
222 bool get _mayAddListener => _state <= _PENDING_COMPLETE; 224 bool get _mayAddListener => _state <= _PENDING_COMPLETE;
223 bool get _isChained => _state == _CHAINED; 225 bool get _isChained => _state == _CHAINED;
224 bool get _isComplete => _state >= _VALUE; 226 bool get _isComplete => _state >= _VALUE;
225 bool get _hasError => _state == _ERROR; 227 bool get _hasError => _state == _ERROR;
226 228
227 void _setChained(_Future source) { 229 void _setChained(_Future source) {
228 assert(_mayAddListener); 230 assert(_mayAddListener);
229 _state = _CHAINED; 231 _state = _CHAINED;
230 _resultOrListeners = source; 232 _resultOrListeners = source;
231 } 233 }
232 234
233 Future<E> then<E>( 235 Future<E> then<E>(FutureOr<E> f(T value), {Function onError}) {
234 FutureOr<E> f(T value), { Function onError }) {
235 Zone currentZone = Zone.current; 236 Zone currentZone = Zone.current;
236 ZoneUnaryCallback registered; 237 ZoneUnaryCallback registered;
237 if (!identical(currentZone, _ROOT_ZONE)) { 238 if (!identical(currentZone, _ROOT_ZONE)) {
238 f = currentZone.registerUnaryCallback<FutureOr<E>, T>(f); 239 f = currentZone.registerUnaryCallback<FutureOr<E>, T>(f);
239 if (onError != null) { 240 if (onError != null) {
240 onError = _registerErrorHandler<E>(onError, currentZone); 241 onError = _registerErrorHandler<E>(onError, currentZone);
241 } 242 }
242 } 243 }
243 return _thenNoZoneRegistration<E>(f, onError); 244 return _thenNoZoneRegistration<E>(f, onError);
244 } 245 }
245 246
246 // This method is used by async/await. 247 // This method is used by async/await.
247 Future<E> _thenNoZoneRegistration<E>(f(T value), Function onError) { 248 Future<E> _thenNoZoneRegistration<E>(f(T value), Function onError) {
248 _Future<E> result = new _Future<E>(); 249 _Future<E> result = new _Future<E>();
249 _addListener(new _FutureListener<T, E>.then(result, f, onError)); 250 _addListener(new _FutureListener<T, E>.then(result, f, onError));
250 return result; 251 return result;
251 } 252 }
252 253
253 Future<T> catchError(Function onError, { bool test(error) }) { 254 Future<T> catchError(Function onError, {bool test(error)}) {
254 _Future<T> result = new _Future<T>(); 255 _Future<T> result = new _Future<T>();
255 if (!identical(result._zone, _ROOT_ZONE)) { 256 if (!identical(result._zone, _ROOT_ZONE)) {
256 onError = _registerErrorHandler<T>(onError, result._zone); 257 onError = _registerErrorHandler<T>(onError, result._zone);
257 if (test != null) test = result._zone.registerUnaryCallback(test); 258 if (test != null) test = result._zone.registerUnaryCallback(test);
258 } 259 }
259 _addListener(new _FutureListener<T, T>.catchError( 260 _addListener(new _FutureListener<T, T>.catchError(result, onError, test));
260 result, onError, test));
261 return result; 261 return result;
262 } 262 }
263 263
264 Future<T> whenComplete(action()) { 264 Future<T> whenComplete(action()) {
265 _Future<T> result = new _Future<T>(); 265 _Future<T> result = new _Future<T>();
266 if (!identical(result._zone, _ROOT_ZONE)) { 266 if (!identical(result._zone, _ROOT_ZONE)) {
267 action = result._zone.registerCallback<dynamic>(action); 267 action = result._zone.registerCallback<dynamic>(action);
268 } 268 }
269 _addListener(new _FutureListener<T, T>.whenComplete(result, action)); 269 _addListener(new _FutureListener<T, T>.whenComplete(result, action));
270 return result; 270 return result;
(...skipping 16 matching lines...) Expand all
287 return _resultOrListeners; 287 return _resultOrListeners;
288 } 288 }
289 289
290 _Future get _chainSource { 290 _Future get _chainSource {
291 assert(_isChained); 291 assert(_isChained);
292 return _resultOrListeners; 292 return _resultOrListeners;
293 } 293 }
294 294
295 // This method is used by async/await. 295 // This method is used by async/await.
296 void _setValue(T value) { 296 void _setValue(T value) {
297 assert(!_isComplete); // But may have a completion pending. 297 assert(!_isComplete); // But may have a completion pending.
298 _state = _VALUE; 298 _state = _VALUE;
299 _resultOrListeners = value; 299 _resultOrListeners = value;
300 } 300 }
301 301
302 void _setErrorObject(AsyncError error) { 302 void _setErrorObject(AsyncError error) {
303 assert(!_isComplete); // But may have a completion pending. 303 assert(!_isComplete); // But may have a completion pending.
304 _state = _ERROR; 304 _state = _ERROR;
305 _resultOrListeners = error; 305 _resultOrListeners = error;
306 } 306 }
307 307
308 void _setError(Object error, StackTrace stackTrace) { 308 void _setError(Object error, StackTrace stackTrace) {
309 _setErrorObject(new AsyncError(error, stackTrace)); 309 _setErrorObject(new AsyncError(error, stackTrace));
310 } 310 }
311 311
312 /// Copy the completion result of [source] into this future. 312 /// Copy the completion result of [source] into this future.
313 /// 313 ///
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 // for _Future than _chainCoreFuture, so you must use _chainCoreFuture 402 // for _Future than _chainCoreFuture, so you must use _chainCoreFuture
403 // in that case. 403 // in that case.
404 static void _chainForeignFuture(Future source, _Future target) { 404 static void _chainForeignFuture(Future source, _Future target) {
405 assert(!target._isComplete); 405 assert(!target._isComplete);
406 assert(source is! _Future); 406 assert(source is! _Future);
407 407
408 // Mark the target as chained (and as such half-completed). 408 // Mark the target as chained (and as such half-completed).
409 target._setPendingComplete(); 409 target._setPendingComplete();
410 try { 410 try {
411 source.then((value) { 411 source.then((value) {
412 assert(target._isPendingComplete); 412 assert(target._isPendingComplete);
413 // The "value" may be another future if the foreign future 413 // The "value" may be another future if the foreign future
414 // implementation is mis-behaving, 414 // implementation is mis-behaving,
415 // so use _complete instead of _completeWithValue. 415 // so use _complete instead of _completeWithValue.
416 target._clearPendingComplete(); // Clear this first, it's set again. 416 target._clearPendingComplete(); // Clear this first, it's set again.
417 target._complete(value); 417 target._complete(value);
418 }, 418 },
419 // TODO(floitsch): eventually we would like to make this non-optional 419 // TODO(floitsch): eventually we would like to make this non-optional
420 // and dependent on the listeners of the target future. If none of 420 // and dependent on the listeners of the target future. If none of
421 // the target future's listeners want to have the stack trace we don't 421 // the target future's listeners want to have the stack trace we don't
422 // need a trace. 422 // need a trace.
423 onError: (error, [stackTrace]) { 423 onError: (error, [stackTrace]) {
424 assert(target._isPendingComplete); 424 assert(target._isPendingComplete);
425 target._completeError(error, stackTrace); 425 target._completeError(error, stackTrace);
426 }); 426 });
427 } catch (e, s) { 427 } catch (e, s) {
428 // This only happens if the `then` call threw synchronously when given 428 // This only happens if the `then` call threw synchronously when given
429 // valid arguments. 429 // valid arguments.
430 // That requires a non-conforming implementation of the Future interface, 430 // That requires a non-conforming implementation of the Future interface,
431 // which should, hopefully, never happen. 431 // which should, hopefully, never happen.
432 scheduleMicrotask(() { 432 scheduleMicrotask(() {
433 target._completeError(e, s); 433 target._completeError(e, s);
434 }); 434 });
435 } 435 }
436 } 436 }
437 437
438 // Take the value (when completed) of source and complete target with that 438 // Take the value (when completed) of source and complete target with that
439 // value (or error). This function expects that source is a _Future. 439 // value (or error). This function expects that source is a _Future.
440 static void _chainCoreFuture(_Future source, _Future target) { 440 static void _chainCoreFuture(_Future source, _Future target) {
441 assert(target._mayAddListener); // Not completed, not already chained. 441 assert(target._mayAddListener); // Not completed, not already chained.
442 while (source._isChained) { 442 while (source._isChained) {
443 source = source._chainSource; 443 source = source._chainSource;
444 } 444 }
445 if (source._isComplete) { 445 if (source._isComplete) {
446 _FutureListener listeners = target._removeListeners(); 446 _FutureListener listeners = target._removeListeners();
447 target._cloneResult(source); 447 target._cloneResult(source);
448 _propagateToListeners(target, listeners); 448 _propagateToListeners(target, listeners);
449 } else { 449 } else {
450 _FutureListener listeners = target._resultOrListeners; 450 _FutureListener listeners = target._resultOrListeners;
451 target._setChained(source); 451 target._setChained(source);
452 source._prependListeners(listeners); 452 source._prependListeners(listeners);
453 } 453 }
454 } 454 }
455 455
456 void _complete(value) { 456 void _complete(value) {
457 assert(!_isComplete); 457 assert(!_isComplete);
458 if (value is Future) { 458 if (value is Future) {
459 if (value is _Future) { 459 if (value is _Future) {
460 _chainCoreFuture(value, this); 460 _chainCoreFuture(value, this);
461 } else { 461 } else {
462 _chainForeignFuture(value, this); 462 _chainForeignFuture(value, this);
463 } 463 }
464 } else { 464 } else {
465 _FutureListener listeners = _removeListeners(); 465 _FutureListener listeners = _removeListeners();
466 _setValue(value as Object /*=T*/); 466 _setValue(value as Object/*=T*/);
467 _propagateToListeners(this, listeners); 467 _propagateToListeners(this, listeners);
468 } 468 }
469 } 469 }
470 470
471 void _completeWithValue(T value) { 471 void _completeWithValue(T value) {
472 assert(!_isComplete); 472 assert(!_isComplete);
473 assert(value is! Future); 473 assert(value is! Future);
474 474
475 _FutureListener listeners = _removeListeners(); 475 _FutureListener listeners = _removeListeners();
476 _setValue(value); 476 _setValue(value);
(...skipping 16 matching lines...) Expand all
493 // The first case means that we must not immediately complete the Future, 493 // The first case means that we must not immediately complete the Future,
494 // as our code would immediately start propagating the error without 494 // as our code would immediately start propagating the error without
495 // giving the time to install error-handlers. 495 // giving the time to install error-handlers.
496 // However the second case requires us to deal with the value immediately. 496 // However the second case requires us to deal with the value immediately.
497 // Otherwise the value could complete with an error and report an 497 // Otherwise the value could complete with an error and report an
498 // unhandled error, even though we know we are already going to listen to 498 // unhandled error, even though we know we are already going to listen to
499 // it. 499 // it.
500 500
501 if (value is Future) { 501 if (value is Future) {
502 // Assign to typed variables so we get earlier checks in checked mode. 502 // Assign to typed variables so we get earlier checks in checked mode.
503 Future<T> typedFuture = value as Object /*=Future<T>*/; 503 Future<T> typedFuture = value as Object/*=Future<T>*/;
504 if (typedFuture is _Future) { 504 if (typedFuture is _Future) {
505 _Future<T> coreFuture = typedFuture; 505 _Future<T> coreFuture = typedFuture;
506 if (coreFuture._hasError) { 506 if (coreFuture._hasError) {
507 // Case 1 from above. Delay completion to enable the user to register 507 // Case 1 from above. Delay completion to enable the user to register
508 // callbacks. 508 // callbacks.
509 _setPendingComplete(); 509 _setPendingComplete();
510 _zone.scheduleMicrotask(() { 510 _zone.scheduleMicrotask(() {
511 _chainCoreFuture(coreFuture, this); 511 _chainCoreFuture(coreFuture, this);
512 }); 512 });
513 } else { 513 } else {
514 _chainCoreFuture(coreFuture, this); 514 _chainCoreFuture(coreFuture, this);
515 } 515 }
516 } else { 516 } else {
517 // Case 2 from above. Chain the future immediately. 517 // Case 2 from above. Chain the future immediately.
518 // Note that we are still completing asynchronously (through 518 // Note that we are still completing asynchronously (through
519 // _chainForeignFuture). 519 // _chainForeignFuture).
520 _chainForeignFuture(typedFuture, this); 520 _chainForeignFuture(typedFuture, this);
521 } 521 }
522 return; 522 return;
523 } 523 }
524 T typedValue = value as Object /*=T*/; 524 T typedValue = value as Object/*=T*/;
525 525
526 _setPendingComplete(); 526 _setPendingComplete();
527 _zone.scheduleMicrotask(() { 527 _zone.scheduleMicrotask(() {
528 _completeWithValue(typedValue); 528 _completeWithValue(typedValue);
529 }); 529 });
530 } 530 }
531 531
532 void _asyncCompleteError(error, StackTrace stackTrace) { 532 void _asyncCompleteError(error, StackTrace stackTrace) {
533 assert(!_isComplete); 533 assert(!_isComplete);
534 534
535 _setPendingComplete(); 535 _setPendingComplete();
536 _zone.scheduleMicrotask(() { 536 _zone.scheduleMicrotask(() {
537 _completeError(error, stackTrace); 537 _completeError(error, stackTrace);
538 }); 538 });
539 } 539 }
540 540
541 /** 541 /**
542 * Propagates the value/error of [source] to its [listeners], executing the 542 * Propagates the value/error of [source] to its [listeners], executing the
543 * listeners' callbacks. 543 * listeners' callbacks.
544 */ 544 */
545 static void _propagateToListeners(_Future source, _FutureListener listeners) { 545 static void _propagateToListeners(_Future source, _FutureListener listeners) {
546 while (true) { 546 while (true) {
547 assert(source._isComplete); 547 assert(source._isComplete);
548 bool hasError = source._hasError; 548 bool hasError = source._hasError;
549 if (listeners == null) { 549 if (listeners == null) {
550 if (hasError) { 550 if (hasError) {
551 AsyncError asyncError = source._error; 551 AsyncError asyncError = source._error;
552 source._zone.handleUncaughtError( 552 source._zone
553 asyncError.error, asyncError.stackTrace); 553 .handleUncaughtError(asyncError.error, asyncError.stackTrace);
554 } 554 }
555 return; 555 return;
556 } 556 }
557 // Usually futures only have one listener. If they have several, we 557 // Usually futures only have one listener. If they have several, we
558 // call handle them separately in recursive calls, continuing 558 // call handle them separately in recursive calls, continuing
559 // here only when there is only one listener left. 559 // here only when there is only one listener left.
560 while (listeners._nextListener != null) { 560 while (listeners._nextListener != null) {
561 _FutureListener listener = listeners; 561 _FutureListener listener = listeners;
562 listeners = listener._nextListener; 562 listeners = listener._nextListener;
563 listener._nextListener = null; 563 listener._nextListener = null;
(...skipping 12 matching lines...) Expand all
576 var listenerValueOrError = sourceResult; 576 var listenerValueOrError = sourceResult;
577 577
578 // Only if we either have an error or callbacks, go into this, somewhat 578 // Only if we either have an error or callbacks, go into this, somewhat
579 // expensive, branch. Here we'll enter/leave the zone. Many futures 579 // expensive, branch. Here we'll enter/leave the zone. Many futures
580 // don't have callbacks, so this is a significant optimization. 580 // don't have callbacks, so this is a significant optimization.
581 if (hasError || listener.handlesValue || listener.handlesComplete) { 581 if (hasError || listener.handlesValue || listener.handlesComplete) {
582 Zone zone = listener._zone; 582 Zone zone = listener._zone;
583 if (hasError && !source._zone.inSameErrorZone(zone)) { 583 if (hasError && !source._zone.inSameErrorZone(zone)) {
584 // Don't cross zone boundaries with errors. 584 // Don't cross zone boundaries with errors.
585 AsyncError asyncError = source._error; 585 AsyncError asyncError = source._error;
586 source._zone.handleUncaughtError( 586 source._zone
587 asyncError.error, asyncError.stackTrace); 587 .handleUncaughtError(asyncError.error, asyncError.stackTrace);
588 return; 588 return;
589 } 589 }
590 590
591 Zone oldZone; 591 Zone oldZone;
592 if (!identical(Zone.current, zone)) { 592 if (!identical(Zone.current, zone)) {
593 // Change zone if it's not current. 593 // Change zone if it's not current.
594 oldZone = Zone._enter(zone); 594 oldZone = Zone._enter(zone);
595 } 595 }
596 596
597 // These callbacks are abstracted to isolate the try/catch blocks 597 // These callbacks are abstracted to isolate the try/catch blocks
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 } catch (e, s) { 652 } catch (e, s) {
653 if (identical(source._error.error, e)) { 653 if (identical(source._error.error, e)) {
654 listenerValueOrError = source._error; 654 listenerValueOrError = source._error;
655 } else { 655 } else {
656 listenerValueOrError = new AsyncError(e, s); 656 listenerValueOrError = new AsyncError(e, s);
657 } 657 }
658 listenerHasError = true; 658 listenerHasError = true;
659 } 659 }
660 } 660 }
661 661
662
663 if (listener.handlesComplete) { 662 if (listener.handlesComplete) {
664 handleWhenCompleteCallback(); 663 handleWhenCompleteCallback();
665 } else if (!hasError) { 664 } else if (!hasError) {
666 if (listener.handlesValue) { 665 if (listener.handlesValue) {
667 handleValueCallback(); 666 handleValueCallback();
668 } 667 }
669 } else { 668 } else {
670 if (listener.handlesError) { 669 if (listener.handlesError) {
671 handleError(); 670 handleError();
672 } 671 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 source = result; 708 source = result;
710 } 709 }
711 } 710 }
712 711
713 Future<T> timeout(Duration timeLimit, {onTimeout()}) { 712 Future<T> timeout(Duration timeLimit, {onTimeout()}) {
714 if (_isComplete) return new _Future.immediate(this); 713 if (_isComplete) return new _Future.immediate(this);
715 _Future<T> result = new _Future<T>(); 714 _Future<T> result = new _Future<T>();
716 Timer timer; 715 Timer timer;
717 if (onTimeout == null) { 716 if (onTimeout == null) {
718 timer = new Timer(timeLimit, () { 717 timer = new Timer(timeLimit, () {
719 result._completeError(new TimeoutException("Future not completed", 718 result._completeError(
720 timeLimit)); 719 new TimeoutException("Future not completed", timeLimit));
721 }); 720 });
722 } else { 721 } else {
723 Zone zone = Zone.current; 722 Zone zone = Zone.current;
724 onTimeout = zone.registerCallback(onTimeout); 723 onTimeout = zone.registerCallback(onTimeout);
725 timer = new Timer(timeLimit, () { 724 timer = new Timer(timeLimit, () {
726 try { 725 try {
727 result._complete(zone.run(onTimeout)); 726 result._complete(zone.run(onTimeout));
728 } catch (e, s) { 727 } catch (e, s) {
729 result._completeError(e, s); 728 result._completeError(e, s);
730 } 729 }
731 }); 730 });
732 } 731 }
733 this.then((T v) { 732 this.then((T v) {
734 if (timer.isActive) { 733 if (timer.isActive) {
735 timer.cancel(); 734 timer.cancel();
736 result._completeWithValue(v); 735 result._completeWithValue(v);
737 } 736 }
738 }, onError: (e, s) { 737 }, onError: (e, s) {
739 if (timer.isActive) { 738 if (timer.isActive) {
740 timer.cancel(); 739 timer.cancel();
741 result._completeError(e, s); 740 result._completeError(e, s);
742 } 741 }
743 }); 742 });
744 return result; 743 return result;
745 } 744 }
746 } 745 }
OLDNEW
« no previous file with comments | « sdk/lib/async/future.dart ('k') | sdk/lib/async/schedule_microtask.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698