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

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

Issue 23534043: Don't wait for asynchronous error handlers. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Use _asyncSetError. 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 deprecatedFutureValue(_FutureImpl future) => 7 deprecatedFutureValue(_FutureImpl future) =>
8 future._isComplete ? future._resultOrListeners : null; 8 future._isComplete ? future._resultOrListeners : null;
9 9
10 abstract class _Completer<T> implements Completer<T> { 10 abstract class _Completer<T> implements Completer<T> {
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 /// forwarded directly to the other future. 174 /// forwarded directly to the other future.
175 static const int _CHAINED = 2; 175 static const int _CHAINED = 2;
176 /// The future has been chained to another future, but there hasn't been 176 /// The future has been chained to another future, but there hasn't been
177 /// any listeners added to this future yet. If it is completed with an 177 /// any listeners added to this future yet. If it is completed with an
178 /// error, the error will be considered unhandled. 178 /// error, the error will be considered unhandled.
179 static const int _CHAINED_UNLISTENED = 6; 179 static const int _CHAINED_UNLISTENED = 6;
180 /// The future has been completed with a value result. 180 /// The future has been completed with a value result.
181 static const int _VALUE = 8; 181 static const int _VALUE = 8;
182 /// The future has been completed with an error result. 182 /// The future has been completed with an error result.
183 static const int _ERROR = 12; 183 static const int _ERROR = 12;
184 /// Extra bit set when the future has been completed with an error result.
185 /// but no listener has been scheduled to receive the error.
186 /// If the bit is still set when a [runAsync] call triggers, the error will
187 /// be reported to the top-level handler.
188 /// Assigning a listener before that time will clear the bit.
189 static const int _UNHANDLED_ERROR = 16;
190 184
191 /** Whether the future is complete, and as what. */ 185 /** Whether the future is complete, and as what. */
192 int _state = _INCOMPLETE; 186 int _state = _INCOMPLETE;
193 187
194 final _Zone _zone = _Zone.current.fork(); 188 final _Zone _zone = _Zone.current.fork();
195 189
196 bool get _isChained => (_state & _CHAINED) != 0; 190 bool get _isChained => (_state & _CHAINED) != 0;
197 bool get _hasChainedListener => _state == _CHAINED; 191 bool get _hasChainedListener => _state == _CHAINED;
198 bool get _isComplete => _state >= _VALUE; 192 bool get _isComplete => _state >= _VALUE;
199 bool get _mayComplete => _state == _INCOMPLETE; 193 bool get _mayComplete => _state == _INCOMPLETE;
200 bool get _hasValue => _state == _VALUE; 194 bool get _hasValue => _state == _VALUE;
201 bool get _hasError => _state >= _ERROR; 195 bool get _hasError => _state >= _ERROR;
202 bool get _hasUnhandledError => _state >= _UNHANDLED_ERROR;
203
204 void _clearUnhandledError() {
205 _state &= ~_UNHANDLED_ERROR;
206 }
207 196
208 /** 197 /**
209 * Either the result, a list of listeners or another future. 198 * Either the result, a list of listeners or another future.
210 * 199 *
211 * The result of the future is either a value or an error. 200 * The result of the future is either a value or an error.
212 * A result is only stored when the future has completed. 201 * A result is only stored when the future has completed.
213 * 202 *
214 * The listeners is an internally linked list of [_FutureListener]s. 203 * The listeners is an internally linked list of [_FutureListener]s.
215 * Listeners are only remembered while the future is not yet complete, 204 * Listeners are only remembered while the future is not yet complete,
216 * and it is not chained to another future. 205 * and it is not chained to another future.
(...skipping 14 matching lines...) Expand all
231 _FutureImpl.immediate(T value) { 220 _FutureImpl.immediate(T value) {
232 _state = _VALUE; 221 _state = _VALUE;
233 _resultOrListeners = value; 222 _resultOrListeners = value;
234 } 223 }
235 224
236 _FutureImpl.immediateError(var error, [Object stackTrace]) { 225 _FutureImpl.immediateError(var error, [Object stackTrace]) {
237 if (stackTrace != null) { 226 if (stackTrace != null) {
238 // Force stack trace onto error, even if it had already one. 227 // Force stack trace onto error, even if it had already one.
239 _attachStackTrace(error, stackTrace); 228 _attachStackTrace(error, stackTrace);
240 } 229 }
241 _setError(error); 230 _asyncSetError(error);
242 } 231 }
243 232
244 factory _FutureImpl.wait(Iterable<Future> futures) { 233 factory _FutureImpl.wait(Iterable<Future> futures) {
245 Completer completer; 234 Completer completer;
246 // List collecting values from the futures. 235 // List collecting values from the futures.
247 // Set to null if an error occurs. 236 // Set to null if an error occurs.
248 List values; 237 List values;
249 void handleError(error) { 238 void handleError(error) {
250 if (values != null) { 239 if (values != null) {
251 values = null; 240 values = null;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 hasListeners = (_state == _CHAINED); // and not _CHAINED_UNLISTENED. 314 hasListeners = (_state == _CHAINED); // and not _CHAINED_UNLISTENED.
326 } else { 315 } else {
327 listeners = _removeListeners(); 316 listeners = _removeListeners();
328 hasListeners = (listeners != null); 317 hasListeners = (listeners != null);
329 } 318 }
330 319
331 _state = _ERROR; 320 _state = _ERROR;
332 _resultOrListeners = error; 321 _resultOrListeners = error;
333 322
334 if (!hasListeners) { 323 if (!hasListeners) {
335 _scheduleUnhandledError(); 324 // TODO(floitsch): Hook this into unhandled error handling.
325 var error = _resultOrListeners;
Lasse Reichstein Nielsen 2013/09/05 09:17:25 Why the alias for error here? Just remove the "var
326 _zone.handleUncaughtError(error);
336 return; 327 return;
337 } 328 }
338 while (listeners != null) { 329 while (listeners != null) {
339 _FutureListener listener = listeners; 330 _FutureListener listener = listeners;
340 listeners = listener._nextListener; 331 listeners = listener._nextListener;
341 listener._nextListener = null; 332 listener._nextListener = null;
342 listener._sendError(error); 333 listener._sendError(error);
343 } 334 }
344 } 335 }
345 336
346 void _asyncSetValue(T value) { 337 void _asyncSetValue(T value) {
347 if (!_mayComplete) throw new StateError("Future already completed"); 338 if (!_mayComplete) throw new StateError("Future already completed");
348 _state = _PENDING_COMPLETE; 339 _state = _PENDING_COMPLETE;
349 runAsync(() { _setValueUnchecked(value); }); 340 runAsync(() { _setValueUnchecked(value); });
350 } 341 }
351 342
352 void _asyncSetError(Object error) { 343 void _asyncSetError(Object error) {
353 if (!_mayComplete) throw new StateError("Future already completed"); 344 if (!_mayComplete) throw new StateError("Future already completed");
354 _state = _PENDING_COMPLETE; 345 _state = _PENDING_COMPLETE;
355 runAsync(() { _setErrorUnchecked(error); }); 346 runAsync(() { _setErrorUnchecked(error); });
356 } 347 }
357 348
358 void _scheduleUnhandledError() {
359 assert(_state == _ERROR);
360 _state = _ERROR | _UNHANDLED_ERROR;
361 // Wait for the rest of the current event's duration to see
362 // if a subscriber is added to handle the error.
363 runAsync(() {
364 if (_hasUnhandledError) {
365 // No error handler has been added since the error was set.
366 _clearUnhandledError();
367 // TODO(floitsch): Hook this into unhandled error handling.
368 var error = _resultOrListeners;
369 _zone.handleUncaughtError(error);
370 }
371 });
372 }
373
374 void _addListener(_FutureListener listener) { 349 void _addListener(_FutureListener listener) {
375 assert(listener._nextListener == null); 350 assert(listener._nextListener == null);
376 if (!listener._inSameErrorZone(_zone)) { 351 if (!listener._inSameErrorZone(_zone)) {
377 listener = new _ErrorZoneBoundaryListener(listener); 352 listener = new _ErrorZoneBoundaryListener(listener);
378 } 353 }
379 if (_isChained) { 354 if (_isChained) {
380 _state = _CHAINED; // In case it was _CHAINED_UNLISTENED. 355 _state = _CHAINED; // In case it was _CHAINED_UNLISTENED.
381 _FutureImpl resultSource = _chainSource; 356 _FutureImpl resultSource = _chainSource;
382 resultSource._addListener(listener); 357 resultSource._addListener(listener);
383 return; 358 return;
384 } 359 }
385 if (_isComplete) { 360 if (_isComplete) {
386 _clearUnhandledError();
387 // Handle late listeners asynchronously. 361 // Handle late listeners asynchronously.
388 runAsync(() { 362 runAsync(() {
389 if (_hasValue) { 363 if (_hasValue) {
390 T value = _resultOrListeners; 364 T value = _resultOrListeners;
391 listener._sendValue(value); 365 listener._sendValue(value);
392 } else { 366 } else {
393 assert(_hasError); 367 assert(_hasError);
394 listener._sendError(_resultOrListeners); 368 listener._sendError(_resultOrListeners);
395 } 369 }
396 }); 370 });
(...skipping 27 matching lines...) Expand all
424 * immediately. This function is only called during event resolution 398 * immediately. This function is only called during event resolution
425 * where it's acceptable to send an event. 399 * where it's acceptable to send an event.
426 */ 400 */
427 void _chain(_FutureImpl future) { 401 void _chain(_FutureImpl future) {
428 if (!_isComplete) { 402 if (!_isComplete) {
429 future._chainFromFuture(this); 403 future._chainFromFuture(this);
430 } else if (_hasValue) { 404 } else if (_hasValue) {
431 future._setValue(_resultOrListeners); 405 future._setValue(_resultOrListeners);
432 } else { 406 } else {
433 assert(_hasError); 407 assert(_hasError);
434 _clearUnhandledError();
435 future._setError(_resultOrListeners); 408 future._setError(_resultOrListeners);
436 } 409 }
437 } 410 }
438 411
439 /** 412 /**
440 * Returns the future that this future is chained to. 413 * Returns the future that this future is chained to.
441 * 414 *
442 * If that future is itself chained to something else, 415 * If that future is itself chained to something else,
443 * get the [_chainSource] of that future instead, and make this 416 * get the [_chainSource] of that future instead, and make this
444 * future chain directly to the earliest source. 417 * future chain directly to the earliest source.
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 _setError(error); 651 _setError(error);
679 }, onError: _setError); 652 }, onError: _setError);
680 return; 653 return;
681 } 654 }
682 } catch (e, s) { 655 } catch (e, s) {
683 error = _asyncError(e, s); 656 error = _asyncError(e, s);
684 } 657 }
685 _setError(error); 658 _setError(error);
686 } 659 }
687 } 660 }
OLDNEW
« no previous file with comments | « no previous file | tests/lib/async/catch_errors15_test.dart » ('j') | tests/lib/async/catch_errors15_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698