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

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: mostly tests. Created 7 years, 7 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> {
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.incrementOpenCallbackCount();
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.decrementOpenCallbackCount();
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.decrementOpenCallbackCount();
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 switches. It guarantees that no
Lasse Reichstein Nielsen 2013/05/21 08:19:57 Need more explanation. What is it installed on? By
floitsch 2013/05/21 18:08:32 Done.
104 * error runs through zone boundaries that change error-handling.
105 */
106 class _ErrorZoneBoundaryListener implements _FutureListener {
107 _FutureListener _nextListener;
108 final _FutureListener _listener;
109
110 _ErrorZoneBoundaryListener(this._listener) {
111 assert(!_nextListener._inSameErrorZone(_Zone.current));
112 }
113
114 bool _inSameErrorZone(_Zone otherZone) {
Lasse Reichstein Nielsen 2013/05/21 08:19:57 Why is it not supported? Could it just return fals
floitsch 2013/05/21 18:08:32 It's basically an assert. It could return anything
115 throw new UnsupportedError(
116 "A Zone boundary doesn't support the inSameErrorZone test.");
117 }
118
119 void _sendValue(value) {
120 _listener._sendValue(value);
121 }
122
123 void _sendError(error) {
124 // We are not allowed to send an error from one error-zone to another.
125 // This is the whole purpose of this class.
126 _Zone.current._addError(error);
127 }
86 } 128 }
87 129
88 class _FutureImpl<T> implements Future<T> { 130 class _FutureImpl<T> implements Future<T> {
89 static const int _INCOMPLETE = 0; 131 static const int _INCOMPLETE = 0;
90 static const int _VALUE = 1; 132 static const int _VALUE = 1;
91 static const int _ERROR = 2; 133 static const int _ERROR = 2;
92 static const int _UNHANDLED_ERROR = 4; 134 static const int _UNHANDLED_ERROR = 4;
93 135
94 /** Whether the future is complete, and as what. */ 136 /** Whether the future is complete, and as what. */
95 int _state = _INCOMPLETE; 137 int _state = _INCOMPLETE;
96 138
139 final _Zone _zone = _Zone.current.fork();
140
97 bool get _isComplete => _state != _INCOMPLETE; 141 bool get _isComplete => _state != _INCOMPLETE;
98 bool get _hasValue => _state == _VALUE; 142 bool get _hasValue => _state == _VALUE;
99 bool get _hasError => (_state & _ERROR) != 0; 143 bool get _hasError => (_state & _ERROR) != 0;
100 bool get _hasUnhandledError => (_state & _UNHANDLED_ERROR) != 0; 144 bool get _hasUnhandledError => (_state & _UNHANDLED_ERROR) != 0;
101 145
102 void _clearUnhandledError() { 146 void _clearUnhandledError() {
103 // Works because _UNHANDLED_ERROR is highest bit in use. 147 // Works because _UNHANDLED_ERROR is highest bit in use.
104 _state &= ~_UNHANDLED_ERROR; 148 _state &= ~_UNHANDLED_ERROR;
105 } 149 }
106 150
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 Future catchError(f(error), { bool test(error) }) { 220 Future catchError(f(error), { bool test(error) }) {
177 return new _CatchErrorFuture(f, test).._subscribeTo(this); 221 return new _CatchErrorFuture(f, test).._subscribeTo(this);
178 } 222 }
179 223
180 Future<T> whenComplete(action()) { 224 Future<T> whenComplete(action()) {
181 return new _WhenFuture<T>(action).._subscribeTo(this); 225 return new _WhenFuture<T>(action).._subscribeTo(this);
182 } 226 }
183 227
184 Stream<T> asStream() => new Stream.fromFuture(this); 228 Stream<T> asStream() => new Stream.fromFuture(this);
185 229
230 bool _inSameErrorZone(_Zone otherZone) {
231 return _zone.inSameErrorZone(otherZone);
232 }
233
186 void _setValue(T value) { 234 void _setValue(T value) {
187 if (_isComplete) throw new StateError("Future already completed"); 235 if (_isComplete) throw new StateError("Future already completed");
188 _FutureListener listeners = _removeListeners(); 236 _FutureListener listeners = _removeListeners();
189 _state = _VALUE; 237 _state = _VALUE;
190 _resultOrListeners = value; 238 _resultOrListeners = value;
191 while (listeners != null) { 239 while (listeners != null) {
192 _FutureListener listener = listeners; 240 _FutureListener listener = listeners;
193 listeners = listener._nextListener; 241 listeners = listener._nextListener;
194 listener._nextListener = null; 242 listener._nextListener = null;
195 listener._sendValue(value); 243 listener._sendValue(value);
(...skipping 19 matching lines...) Expand all
215 263
216 void _scheduleUnhandledError() { 264 void _scheduleUnhandledError() {
217 _state |= _UNHANDLED_ERROR; 265 _state |= _UNHANDLED_ERROR;
218 // Wait for the rest of the current event's duration to see 266 // Wait for the rest of the current event's duration to see
219 // if a subscriber is added to handle the error. 267 // if a subscriber is added to handle the error.
220 runAsync(() { 268 runAsync(() {
221 if (_hasUnhandledError) { 269 if (_hasUnhandledError) {
222 // No error handler has been added since the error was set. 270 // No error handler has been added since the error was set.
223 _clearUnhandledError(); 271 _clearUnhandledError();
224 var error = _resultOrListeners; 272 var error = _resultOrListeners;
225 print("Uncaught Error: ${error}"); 273 _zone.handleUncaughtError(error);
226 var trace = getAttachedStackTrace(error);
227 if (trace != null) {
228 print("Stack Trace:\n$trace\n");
229 }
230 throw error;
231 } 274 }
232 }); 275 });
233 } 276 }
234 277
235 void _addListener(_FutureListener listener) { 278 void _addListener(_FutureListener listener) {
279 assert(listener._nextListener == null);
280 if (!listener._inSameErrorZone(_zone)) {
281 listener = new _ErrorZoneBoundaryListener(listener);
282 }
236 if (_isComplete) { 283 if (_isComplete) {
237 _clearUnhandledError(); 284 _clearUnhandledError();
238 // Handle late listeners asynchronously. 285 // Handle late listeners asynchronously.
239 runAsync(() { 286 runAsync(() {
240 if (_hasValue) { 287 if (_hasValue) {
241 T value = _resultOrListeners; 288 T value = _resultOrListeners;
242 listener._sendValue(value); 289 listener._sendValue(value);
243 } else { 290 } else {
244 assert(_hasError); 291 assert(_hasError);
245 listener._sendError(_resultOrListeners); 292 listener._sendError(_resultOrListeners);
246 } 293 }
247 }); 294 });
248 } else { 295 } else {
249 assert(!_isComplete); 296 assert(!_isComplete);
250 assert(listener._nextListener == null);
251 listener._nextListener = _resultOrListeners; 297 listener._nextListener = _resultOrListeners;
252 _resultOrListeners = listener; 298 _resultOrListeners = listener;
253 } 299 }
254 } 300 }
255 301
256 _FutureListener _removeListeners() { 302 _FutureListener _removeListeners() {
257 // Reverse listeners before returning them, so the resulting list is in 303 // Reverse listeners before returning them, so the resulting list is in
258 // subscription order. 304 // subscription order.
259 assert(!_isComplete); 305 assert(!_isComplete);
260 _FutureListener current = _resultOrListeners; 306 _FutureListener current = _resultOrListeners;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 * 367 *
322 * A transforming future is itself a future and a future listener. 368 * A transforming future is itself a future and a future listener.
323 * Subclasses override [_sendValue]/[_sendError] to intercept 369 * Subclasses override [_sendValue]/[_sendError] to intercept
324 * the results of a previous future. 370 * the results of a previous future.
325 */ 371 */
326 abstract class _TransformFuture<S, T> extends _FutureImpl<T> 372 abstract class _TransformFuture<S, T> extends _FutureImpl<T>
327 implements _FutureListener<S> { 373 implements _FutureListener<S> {
328 // _FutureListener implementation. 374 // _FutureListener implementation.
329 _FutureListener _nextListener; 375 _FutureListener _nextListener;
330 376
331 void _sendValue(S value); 377 _TransformFuture() {
378 _zone.incrementOpenCallbackCount();
379 }
332 380
333 void _sendError(error); 381 void _sendValue(S value) {
382 _zone.executeCallback(() => _zonedSendValue(value));
383 }
384
385 void _sendError(error) {
386 _zone.executeCallback(() => _zonedSendError(error));
387 }
334 388
335 void _subscribeTo(_FutureImpl future) { 389 void _subscribeTo(_FutureImpl future) {
336 future._addListener(this); 390 future._addListener(this);
337 } 391 }
392
393 void _zonedSendValue(S value);
394 void _zonedSendError(error);
338 } 395 }
339 396
340 /** The onValue and onError handlers return either a value or a future */ 397 /** The onValue and onError handlers return either a value or a future */
341 typedef dynamic _FutureOnValue<T>(T value); 398 typedef dynamic _FutureOnValue<T>(T value);
342 typedef dynamic _FutureOnError(error); 399 typedef dynamic _FutureOnError(error);
343 /** Test used by [Future.catchError] to handle skip some errors. */ 400 /** Test used by [Future.catchError] to handle skip some errors. */
344 typedef bool _FutureErrorTest(var error); 401 typedef bool _FutureErrorTest(var error);
345 /** Used by [WhenFuture]. */ 402 /** Used by [WhenFuture]. */
346 typedef _FutureAction(); 403 typedef _FutureAction();
347 404
348 /** Future returned by [Future.then] with no [:onError:] parameter. */ 405 /** Future returned by [Future.then] with no [:onError:] parameter. */
349 class _ThenFuture<S, T> extends _TransformFuture<S, T> { 406 class _ThenFuture<S, T> extends _TransformFuture<S, T> {
350 // TODO(ahe): Restore type when feature is implemented in dart2js 407 // TODO(ahe): Restore type when feature is implemented in dart2js
351 // checked mode. 408 // checked mode.
352 final /* _FutureOnValue<S> */ _onValue; 409 final /* _FutureOnValue<S> */ _onValue;
353 410
354 _ThenFuture(this._onValue); 411 _ThenFuture(this._onValue);
355 412
356 _sendValue(S value) { 413 _zonedSendValue(S value) {
357 assert(_onValue != null); 414 assert(_onValue != null);
358 var result; 415 var result;
359 try { 416 try {
360 result = _onValue(value); 417 result = _onValue(value);
361 } catch (e, s) { 418 } catch (e, s) {
362 _setError(_asyncError(e, s)); 419 _setError(_asyncError(e, s));
363 return; 420 return;
364 } 421 }
365 _setOrChainValue(result); 422 _setOrChainValue(result);
366 } 423 }
367 424
368 void _sendError(error) { 425 void _zonedSendError(error) {
369 _setError(error); 426 _setError(error);
370 } 427 }
371 } 428 }
372 429
373 /** Future returned by [Future.catchError]. */ 430 /** Future returned by [Future.catchError]. */
374 class _CatchErrorFuture<T> extends _TransformFuture<T,T> { 431 class _CatchErrorFuture<T> extends _TransformFuture<T,T> {
375 final _FutureErrorTest _test; 432 final _FutureErrorTest _test;
376 final _FutureOnError _onError; 433 final _FutureOnError _onError;
377 434
378 _CatchErrorFuture(this._onError, this._test); 435 _CatchErrorFuture(this._onError, this._test);
379 436
380 _sendValue(T value) { 437 _zonedSendValue(T value) {
381 _setValue(value); 438 _setValue(value);
382 } 439 }
383 440
384 _sendError(error) { 441 _zonedSendError(error) {
385 assert(_onError != null); 442 assert(_onError != null);
386 // if _test is supplied, check if it returns true, otherwise just 443 // if _test is supplied, check if it returns true, otherwise just
387 // forward the error unmodified. 444 // forward the error unmodified.
388 if (_test != null) { 445 if (_test != null) {
389 bool matchesTest; 446 bool matchesTest;
390 try { 447 try {
391 matchesTest = _test(error); 448 matchesTest = _test(error);
392 } catch (e, s) { 449 } catch (e, s) {
393 _setError(_asyncError(e, s)); 450 _setError(_asyncError(e, s));
394 return; 451 return;
(...skipping 16 matching lines...) Expand all
411 } 468 }
412 469
413 /** Future returned by [Future.then] with an [:onError:] parameter. */ 470 /** Future returned by [Future.then] with an [:onError:] parameter. */
414 class _SubscribeFuture<S, T> extends _ThenFuture<S, T> { 471 class _SubscribeFuture<S, T> extends _ThenFuture<S, T> {
415 final _FutureOnError _onError; 472 final _FutureOnError _onError;
416 473
417 _SubscribeFuture(onValue(S value), this._onError) : super(onValue); 474 _SubscribeFuture(onValue(S value), this._onError) : super(onValue);
418 475
419 // The _sendValue method is inherited from ThenFuture. 476 // The _sendValue method is inherited from ThenFuture.
420 477
421 void _sendError(error) { 478 void _zonedSendError(error) {
422 assert(_onError != null); 479 assert(_onError != null);
423 var result; 480 var result;
424 try { 481 try {
425 result = _onError(error); 482 result = _onError(error);
426 } catch (e, s) { 483 } catch (e, s) {
427 _setError(_asyncError(e, s)); 484 _setError(_asyncError(e, s));
428 return; 485 return;
429 } 486 }
430 _setOrChainValue(result); 487 _setOrChainValue(result);
431 } 488 }
432 } 489 }
433 490
434 /** Future returned by [Future.whenComplete]. */ 491 /** Future returned by [Future.whenComplete]. */
435 class _WhenFuture<T> extends _TransformFuture<T, T> { 492 class _WhenFuture<T> extends _TransformFuture<T, T> {
436 final _FutureAction _action; 493 final _FutureAction _action;
437 494
438 _WhenFuture(this._action); 495 _WhenFuture(this._action);
439 496
440 void _sendValue(T value) { 497 void _zonedSendValue(T value) {
441 try { 498 try {
442 var result = _action(); 499 var result = _action();
443 if (result is Future) { 500 if (result is Future) {
444 Future resultFuture = result; 501 Future resultFuture = result;
445 resultFuture.then((_) { 502 resultFuture.then((_) {
446 _setValue(value); 503 _setValue(value);
447 }, onError: _setError); 504 }, onError: _setError);
448 return; 505 return;
449 } 506 }
450 } catch (e, s) { 507 } catch (e, s) {
451 _setError(_asyncError(e, s)); 508 _setError(_asyncError(e, s));
452 return; 509 return;
453 } 510 }
454 _setValue(value); 511 _setValue(value);
455 } 512 }
456 513
457 void _sendError(error) { 514 void _zonedSendError(error) {
458 try { 515 try {
459 var result = _action(); 516 var result = _action();
460 if (result is Future) { 517 if (result is Future) {
461 Future resultFuture = result; 518 Future resultFuture = result;
462 // TODO(lrn): Find a way to combine [error] into [e]. 519 // TODO(lrn): Find a way to combine [error] into [e].
463 resultFuture.then((_) { 520 resultFuture.then((_) {
464 _setError(error); 521 _setError(error);
465 }, onError: _setError); 522 }, onError: _setError);
466 return; 523 return;
467 } 524 }
468 } catch (e, s) { 525 } catch (e, s) {
469 error = _asyncError(e, s); 526 error = _asyncError(e, s);
470 } 527 }
471 _setError(error); 528 _setError(error);
472 } 529 }
473 } 530 }
OLDNEW
« no previous file with comments | « sdk/lib/async/event_loop.dart ('k') | sdk/lib/async/zone.dart » ('j') | sdk/lib/async/zone.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698