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

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

Issue 14973006: Zone support for Futures. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase Created 7 years, 6 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/async/event_loop.dart ('k') | sdk/lib/async/zone.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 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> {
11 final Future<T> future; 11 final Future<T> future;
12 bool _isComplete = false; 12 bool _isComplete = false;
13 13
14 _Completer() : future = new _FutureImpl<T>(); 14 _Completer() : future = new _FutureImpl<T>() {
15 _FutureImpl futureImpl = future;
16 futureImpl._zone.expectCallback();
17 }
15 18
16 void _setFutureValue(T value); 19 void _setFutureValue(T value);
17 void _setFutureError(error); 20 void _setFutureError(error);
18 21
19 void complete([T value]) { 22 void complete([T value]) {
20 if (_isComplete) throw new StateError("Future already completed"); 23 if (_isComplete) throw new StateError("Future already completed");
21 _isComplete = true; 24 _isComplete = true;
25 _FutureImpl futureImpl = future;
26 futureImpl._zone.unexpectCallback();
22 _setFutureValue(value); 27 _setFutureValue(value);
23 } 28 }
24 29
25 void completeError(Object error, [Object stackTrace = null]) { 30 void completeError(Object error, [Object stackTrace = null]) {
26 if (_isComplete) throw new StateError("Future already completed"); 31 if (_isComplete) throw new StateError("Future already completed");
27 _isComplete = true; 32 _isComplete = true;
28 if (stackTrace != null) { 33 if (stackTrace != null) {
29 // Force the stack trace onto the error, even if it already had one. 34 // Force the stack trace onto the error, even if it already had one.
30 _attachStackTrace(error, stackTrace); 35 _attachStackTrace(error, stackTrace);
31 } 36 }
32 _setFutureError(error); 37 _FutureImpl futureImpl = future;
38 if (futureImpl._inSameErrorZone(_Zone.current)) {
39 futureImpl._zone.unexpectCallback();
40 _setFutureError(error);
41 } else {
42 _Zone.current.handleUncaughtError(error);
43 }
33 } 44 }
34 45
35 bool get isCompleted => _isComplete; 46 bool get isCompleted => _isComplete;
36 } 47 }
37 48
38 class _AsyncCompleter<T> extends _Completer<T> { 49 class _AsyncCompleter<T> extends _Completer<T> {
39 void _setFutureValue(T value) { 50 void _setFutureValue(T value) {
40 _FutureImpl future = this.future; 51 _FutureImpl future = this.future;
41 runAsync(() { future._setValue(value); }); 52 runAsync(() { future._setValue(value); });
42 } 53 }
(...skipping 24 matching lines...) Expand all
67 * 78 *
68 * Listeners are kept in a linked list. 79 * Listeners are kept in a linked list.
69 */ 80 */
70 abstract class _FutureListener<T> { 81 abstract class _FutureListener<T> {
71 _FutureListener _nextListener; 82 _FutureListener _nextListener;
72 factory _FutureListener.wrap(_FutureImpl future) { 83 factory _FutureListener.wrap(_FutureImpl future) {
73 return new _FutureListenerWrapper(future); 84 return new _FutureListenerWrapper(future);
74 } 85 }
75 void _sendValue(T value); 86 void _sendValue(T value);
76 void _sendError(error); 87 void _sendError(error);
88
89 bool _inSameErrorZone(_Zone otherZone);
77 } 90 }
78 91
79 /** Adapter for a [_FutureImpl] to be a future result listener. */ 92 /** Adapter for a [_FutureImpl] to be a future result listener. */
80 class _FutureListenerWrapper<T> implements _FutureListener<T> { 93 class _FutureListenerWrapper<T> implements _FutureListener<T> {
81 _FutureImpl future; 94 _FutureImpl future;
82 _FutureListener _nextListener; 95 _FutureListener _nextListener;
83 _FutureListenerWrapper(this.future); 96 _FutureListenerWrapper(this.future);
84 _sendValue(T value) { future._setValue(value); } 97 _sendValue(T value) { future._setValue(value); }
85 _sendError(error) { future._setError(error); } 98 _sendError(error) { future._setError(error); }
99 bool _inSameErrorZone(_Zone otherZone) => future._inSameErrorZone(otherZone);
100 }
101
102 /**
103 * This listener is installed at error-zone boundaries. It signals an
104 * uncaught error in the zone of origin when an error is sent from one error
105 * zone to another.
106 *
107 * When a Future is listening to another Future and they have not been
108 * instantiated in the same error-zone then Futures put an instance of this
109 * class between them (see [_FutureImpl._addListener]).
110 *
111 * For example:
112 *
113 * var completer = new Completer();
114 * var future = completer.future.then((x) => x);
115 * catchErrors(() {
116 * var future2 = future.catchError(print);
117 * });
118 * completer.completeError(499);
119 *
120 * In this example `future` and `future2` are in different error-zones. The
121 * error (499) that originates outside `catchErrors` must not reach the
122 * `catchError` future (`future2`) inside `catchErrors`.
123 *
124 * When invoking `catchError` on `future` the Future installs an
125 * [_ErrorZoneBoundaryListener] between itself and the result, `future2`.
126 *
127 * Conceptually _ErrorZoneBoundaryListeners could be implemented as
128 * `catchError`s on the origin future as well.
129 */
130 class _ErrorZoneBoundaryListener implements _FutureListener {
131 _FutureListener _nextListener;
132 final _FutureListener _listener;
133
134 _ErrorZoneBoundaryListener(this._listener);
135
136 bool _inSameErrorZone(_Zone otherZone) {
137 // Should never be called. We use [_inSameErrorZone] to know if we have
138 // to insert an instance of [_ErrorZoneBoundaryListener] (and in the
139 // controller). Once we have inserted one we should never need to use it
140 // anymore.
141 // It would be valid to `return true` instead.
142 throw new UnsupportedError(
143 "A Zone boundary doesn't support the inSameErrorZone test.");
144 }
145
146 void _sendValue(value) {
147 _listener._sendValue(value);
148 }
149
150 void _sendError(error) {
151 // We are not allowed to send an error from one error-zone to another.
152 // This is the whole purpose of this class.
153 _Zone.current.handleUncaughtError(error);
154 }
86 } 155 }
87 156
88 class _FutureImpl<T> implements Future<T> { 157 class _FutureImpl<T> implements Future<T> {
89 // State of the future. The state determines the interpretation of the 158 // State of the future. The state determines the interpretation of the
90 // [resultOrListeners] field. 159 // [resultOrListeners] field.
91 // TODO(lrn): rename field since it can also contain a chained future. 160 // TODO(lrn): rename field since it can also contain a chained future.
92 161
93 /// Initial state, waiting for a result. In this state, the 162 /// Initial state, waiting for a result. In this state, the
94 /// [resultOrListeners] field holds a single-linked list of 163 /// [resultOrListeners] field holds a single-linked list of
95 /// [FutureListener] listeners. 164 /// [FutureListener] listeners.
(...skipping 15 matching lines...) Expand all
111 /// Extra bit set when the future has been completed with an error result. 180 /// Extra bit set when the future has been completed with an error result.
112 /// but no listener has been scheduled to receive the error. 181 /// but no listener has been scheduled to receive the error.
113 /// If the bit is still set when a [runAsync] call triggers, the error will 182 /// If the bit is still set when a [runAsync] call triggers, the error will
114 /// be reported to the top-level handler. 183 /// be reported to the top-level handler.
115 /// Assigning a listener before that time will clear the bit. 184 /// Assigning a listener before that time will clear the bit.
116 static const int _UNHANDLED_ERROR = 8; 185 static const int _UNHANDLED_ERROR = 8;
117 186
118 /** Whether the future is complete, and as what. */ 187 /** Whether the future is complete, and as what. */
119 int _state = _INCOMPLETE; 188 int _state = _INCOMPLETE;
120 189
190 final _Zone _zone = _Zone.current.fork();
191
121 bool get _isChained => (_state & _CHAINED) != 0; 192 bool get _isChained => (_state & _CHAINED) != 0;
122 bool get _hasChainedListener => _state == _CHAINED; 193 bool get _hasChainedListener => _state == _CHAINED;
123 bool get _isComplete => _state >= _VALUE; 194 bool get _isComplete => _state >= _VALUE;
124 bool get _hasValue => _state == _VALUE; 195 bool get _hasValue => _state == _VALUE;
125 bool get _hasError => _state >= _ERROR; 196 bool get _hasError => _state >= _ERROR;
126 bool get _hasUnhandledError => _state >= _UNHANDLED_ERROR; 197 bool get _hasUnhandledError => _state >= _UNHANDLED_ERROR;
127 198
128 void _clearUnhandledError() { 199 void _clearUnhandledError() {
129 _state &= ~_UNHANDLED_ERROR; 200 _state &= ~_UNHANDLED_ERROR;
130 } 201 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 Future catchError(f(error), { bool test(error) }) { 279 Future catchError(f(error), { bool test(error) }) {
209 return new _CatchErrorFuture(f, test).._subscribeTo(this); 280 return new _CatchErrorFuture(f, test).._subscribeTo(this);
210 } 281 }
211 282
212 Future<T> whenComplete(action()) { 283 Future<T> whenComplete(action()) {
213 return new _WhenFuture<T>(action).._subscribeTo(this); 284 return new _WhenFuture<T>(action).._subscribeTo(this);
214 } 285 }
215 286
216 Stream<T> asStream() => new Stream.fromFuture(this); 287 Stream<T> asStream() => new Stream.fromFuture(this);
217 288
289 bool _inSameErrorZone(_Zone otherZone) {
290 return _zone.inSameErrorZone(otherZone);
291 }
292
218 void _setValue(T value) { 293 void _setValue(T value) {
219 if (_isComplete) throw new StateError("Future already completed"); 294 if (_isComplete) throw new StateError("Future already completed");
220 _FutureListener listeners = _isChained ? null : _removeListeners(); 295 _FutureListener listeners = _isChained ? null : _removeListeners();
221 _state = _VALUE; 296 _state = _VALUE;
222 _resultOrListeners = value; 297 _resultOrListeners = value;
223 while (listeners != null) { 298 while (listeners != null) {
224 _FutureListener listener = listeners; 299 _FutureListener listener = listeners;
225 listeners = listener._nextListener; 300 listeners = listener._nextListener;
226 listener._nextListener = null; 301 listener._nextListener = null;
227 listener._sendValue(value); 302 listener._sendValue(value);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 assert(_state == _ERROR); 335 assert(_state == _ERROR);
261 _state = _ERROR | _UNHANDLED_ERROR; 336 _state = _ERROR | _UNHANDLED_ERROR;
262 // Wait for the rest of the current event's duration to see 337 // Wait for the rest of the current event's duration to see
263 // if a subscriber is added to handle the error. 338 // if a subscriber is added to handle the error.
264 runAsync(() { 339 runAsync(() {
265 if (_hasUnhandledError) { 340 if (_hasUnhandledError) {
266 // No error handler has been added since the error was set. 341 // No error handler has been added since the error was set.
267 _clearUnhandledError(); 342 _clearUnhandledError();
268 // TODO(floitsch): Hook this into unhandled error handling. 343 // TODO(floitsch): Hook this into unhandled error handling.
269 var error = _resultOrListeners; 344 var error = _resultOrListeners;
270 print("Uncaught Error: ${error}"); 345 _zone.handleUncaughtError(error);
271 var trace = getAttachedStackTrace(error);
272 if (trace != null) {
273 print("Stack Trace:\n$trace\n");
274 }
275 throw error;
276 } 346 }
277 }); 347 });
278 } 348 }
279 349
280 void _addListener(_FutureListener listener) { 350 void _addListener(_FutureListener listener) {
351 assert(listener._nextListener == null);
352 if (!listener._inSameErrorZone(_zone)) {
353 listener = new _ErrorZoneBoundaryListener(listener);
354 }
281 if (_isChained) { 355 if (_isChained) {
282 _state = _CHAINED; // In case it was _CHAINED_UNLISTENED. 356 _state = _CHAINED; // In case it was _CHAINED_UNLISTENED.
283 _FutureImpl resultSource = _chainSource; 357 _FutureImpl resultSource = _chainSource;
284 resultSource._addListener(listener); 358 resultSource._addListener(listener);
285 return; 359 return;
286 } 360 }
287 if (_isComplete) { 361 if (_isComplete) {
288 _clearUnhandledError(); 362 _clearUnhandledError();
289 // Handle late listeners asynchronously. 363 // Handle late listeners asynchronously.
290 runAsync(() { 364 runAsync(() {
291 if (_hasValue) { 365 if (_hasValue) {
292 T value = _resultOrListeners; 366 T value = _resultOrListeners;
293 listener._sendValue(value); 367 listener._sendValue(value);
294 } else { 368 } else {
295 assert(_hasError); 369 assert(_hasError);
296 listener._sendError(_resultOrListeners); 370 listener._sendError(_resultOrListeners);
297 } 371 }
298 }); 372 });
299 } else { 373 } else {
300 assert(!_isComplete); 374 assert(!_isComplete);
301 assert(listener._nextListener == null);
302 listener._nextListener = _resultOrListeners; 375 listener._nextListener = _resultOrListeners;
303 _resultOrListeners = listener; 376 _resultOrListeners = listener;
304 } 377 }
305 } 378 }
306 379
307 _FutureListener _removeListeners() { 380 _FutureListener _removeListeners() {
308 // Reverse listeners before returning them, so the resulting list is in 381 // Reverse listeners before returning them, so the resulting list is in
309 // subscription order. 382 // subscription order.
310 assert(!_isComplete); 383 assert(!_isComplete);
311 _FutureListener current = _resultOrListeners; 384 _FutureListener current = _resultOrListeners;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 * 500 *
428 * A transforming future is itself a future and a future listener. 501 * A transforming future is itself a future and a future listener.
429 * Subclasses override [_sendValue]/[_sendError] to intercept 502 * Subclasses override [_sendValue]/[_sendError] to intercept
430 * the results of a previous future. 503 * the results of a previous future.
431 */ 504 */
432 abstract class _TransformFuture<S, T> extends _FutureImpl<T> 505 abstract class _TransformFuture<S, T> extends _FutureImpl<T>
433 implements _FutureListener<S> { 506 implements _FutureListener<S> {
434 // _FutureListener implementation. 507 // _FutureListener implementation.
435 _FutureListener _nextListener; 508 _FutureListener _nextListener;
436 509
437 void _sendValue(S value); 510 _TransformFuture() {
511 _zone.expectCallback();
512 }
438 513
439 void _sendError(error); 514 void _sendValue(S value) {
515 _zone.executeCallback(() => _zonedSendValue(value));
516 }
517
518 void _sendError(error) {
519 _zone.executeCallback(() => _zonedSendError(error));
520 }
440 521
441 void _subscribeTo(_FutureImpl future) { 522 void _subscribeTo(_FutureImpl future) {
442 future._addListener(this); 523 future._addListener(this);
443 } 524 }
525
526 void _zonedSendValue(S value);
527 void _zonedSendError(error);
444 } 528 }
445 529
446 /** The onValue and onError handlers return either a value or a future */ 530 /** The onValue and onError handlers return either a value or a future */
447 typedef dynamic _FutureOnValue<T>(T value); 531 typedef dynamic _FutureOnValue<T>(T value);
448 typedef dynamic _FutureOnError(error); 532 typedef dynamic _FutureOnError(error);
449 /** Test used by [Future.catchError] to handle skip some errors. */ 533 /** Test used by [Future.catchError] to handle skip some errors. */
450 typedef bool _FutureErrorTest(var error); 534 typedef bool _FutureErrorTest(var error);
451 /** Used by [WhenFuture]. */ 535 /** Used by [WhenFuture]. */
452 typedef _FutureAction(); 536 typedef _FutureAction();
453 537
454 /** Future returned by [Future.then] with no [:onError:] parameter. */ 538 /** Future returned by [Future.then] with no [:onError:] parameter. */
455 class _ThenFuture<S, T> extends _TransformFuture<S, T> { 539 class _ThenFuture<S, T> extends _TransformFuture<S, T> {
456 // TODO(ahe): Restore type when feature is implemented in dart2js 540 // TODO(ahe): Restore type when feature is implemented in dart2js
457 // checked mode. 541 // checked mode.
458 final /* _FutureOnValue<S> */ _onValue; 542 final /* _FutureOnValue<S> */ _onValue;
459 543
460 _ThenFuture(this._onValue); 544 _ThenFuture(this._onValue);
461 545
462 _sendValue(S value) { 546 _zonedSendValue(S value) {
463 assert(_onValue != null); 547 assert(_onValue != null);
464 var result; 548 var result;
465 try { 549 try {
466 result = _onValue(value); 550 result = _onValue(value);
467 } catch (e, s) { 551 } catch (e, s) {
468 _setError(_asyncError(e, s)); 552 _setError(_asyncError(e, s));
469 return; 553 return;
470 } 554 }
471 _setOrChainValue(result); 555 _setOrChainValue(result);
472 } 556 }
473 557
474 void _sendError(error) { 558 void _zonedSendError(error) {
475 _setError(error); 559 _setError(error);
476 } 560 }
477 } 561 }
478 562
479 /** Future returned by [Future.catchError]. */ 563 /** Future returned by [Future.catchError]. */
480 class _CatchErrorFuture<T> extends _TransformFuture<T,T> { 564 class _CatchErrorFuture<T> extends _TransformFuture<T,T> {
481 final _FutureErrorTest _test; 565 final _FutureErrorTest _test;
482 final _FutureOnError _onError; 566 final _FutureOnError _onError;
483 567
484 _CatchErrorFuture(this._onError, this._test); 568 _CatchErrorFuture(this._onError, this._test);
485 569
486 _sendValue(T value) { 570 _zonedSendValue(T value) {
487 _setValue(value); 571 _setValue(value);
488 } 572 }
489 573
490 _sendError(error) { 574 _zonedSendError(error) {
491 assert(_onError != null); 575 assert(_onError != null);
492 // if _test is supplied, check if it returns true, otherwise just 576 // if _test is supplied, check if it returns true, otherwise just
493 // forward the error unmodified. 577 // forward the error unmodified.
494 if (_test != null) { 578 if (_test != null) {
495 bool matchesTest; 579 bool matchesTest;
496 try { 580 try {
497 matchesTest = _test(error); 581 matchesTest = _test(error);
498 } catch (e, s) { 582 } catch (e, s) {
499 _setError(_asyncError(e, s)); 583 _setError(_asyncError(e, s));
500 return; 584 return;
(...skipping 16 matching lines...) Expand all
517 } 601 }
518 602
519 /** Future returned by [Future.then] with an [:onError:] parameter. */ 603 /** Future returned by [Future.then] with an [:onError:] parameter. */
520 class _SubscribeFuture<S, T> extends _ThenFuture<S, T> { 604 class _SubscribeFuture<S, T> extends _ThenFuture<S, T> {
521 final _FutureOnError _onError; 605 final _FutureOnError _onError;
522 606
523 _SubscribeFuture(onValue(S value), this._onError) : super(onValue); 607 _SubscribeFuture(onValue(S value), this._onError) : super(onValue);
524 608
525 // The _sendValue method is inherited from ThenFuture. 609 // The _sendValue method is inherited from ThenFuture.
526 610
527 void _sendError(error) { 611 void _zonedSendError(error) {
528 assert(_onError != null); 612 assert(_onError != null);
529 var result; 613 var result;
530 try { 614 try {
531 result = _onError(error); 615 result = _onError(error);
532 } catch (e, s) { 616 } catch (e, s) {
533 _setError(_asyncError(e, s)); 617 _setError(_asyncError(e, s));
534 return; 618 return;
535 } 619 }
536 _setOrChainValue(result); 620 _setOrChainValue(result);
537 } 621 }
538 } 622 }
539 623
540 /** Future returned by [Future.whenComplete]. */ 624 /** Future returned by [Future.whenComplete]. */
541 class _WhenFuture<T> extends _TransformFuture<T, T> { 625 class _WhenFuture<T> extends _TransformFuture<T, T> {
542 final _FutureAction _action; 626 final _FutureAction _action;
543 627
544 _WhenFuture(this._action); 628 _WhenFuture(this._action);
545 629
546 void _sendValue(T value) { 630 void _zonedSendValue(T value) {
547 try { 631 try {
548 var result = _action(); 632 var result = _action();
549 if (result is Future) { 633 if (result is Future) {
550 Future resultFuture = result; 634 Future resultFuture = result;
551 resultFuture.then((_) { 635 resultFuture.then((_) {
552 _setValue(value); 636 _setValue(value);
553 }, onError: _setError); 637 }, onError: _setError);
554 return; 638 return;
555 } 639 }
556 } catch (e, s) { 640 } catch (e, s) {
557 _setError(_asyncError(e, s)); 641 _setError(_asyncError(e, s));
558 return; 642 return;
559 } 643 }
560 _setValue(value); 644 _setValue(value);
561 } 645 }
562 646
563 void _sendError(error) { 647 void _zonedSendError(error) {
564 try { 648 try {
565 var result = _action(); 649 var result = _action();
566 if (result is Future) { 650 if (result is Future) {
567 Future resultFuture = result; 651 Future resultFuture = result;
568 // TODO(lrn): Find a way to combine [error] into [e]. 652 // TODO(lrn): Find a way to combine [error] into [e].
569 resultFuture.then((_) { 653 resultFuture.then((_) {
570 _setError(error); 654 _setError(error);
571 }, onError: _setError); 655 }, onError: _setError);
572 return; 656 return;
573 } 657 }
574 } catch (e, s) { 658 } catch (e, s) {
575 error = _asyncError(e, s); 659 error = _asyncError(e, s);
576 } 660 }
577 _setError(error); 661 _setError(error);
578 } 662 }
579 } 663 }
OLDNEW
« no previous file with comments | « sdk/lib/async/event_loop.dart ('k') | sdk/lib/async/zone.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698