| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 /** | 7 /** |
| 8 * A Zone represents the asynchronous version of a dynamic extent. Asynchronous | 8 * A Zone represents the asynchronous version of a dynamic extent. Asynchronous |
| 9 * callbacks are executed in the zone they have been queued in. For example, | 9 * callbacks are executed in the zone they have been queued in. For example, |
| 10 * the callback of a `future.then` is executed in the same zone as the one where | 10 * the callback of a `future.then` is executed in the same zone as the one where |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 | 55 |
| 56 /** | 56 /** |
| 57 * Executes the given callback in this zone. | 57 * Executes the given callback in this zone. |
| 58 * | 58 * |
| 59 * Decrements the number of callbacks this zone is waiting for (see | 59 * Decrements the number of callbacks this zone is waiting for (see |
| 60 * [expectCallback]). | 60 * [expectCallback]). |
| 61 */ | 61 */ |
| 62 void executeCallback(void fun()); | 62 void executeCallback(void fun()); |
| 63 | 63 |
| 64 /** | 64 /** |
| 65 * Same as [executeCallback] but catches uncaught errors and gives them to |
| 66 * [handleUncaughtError]. |
| 67 */ |
| 68 void executeCallbackGuarded(void fun()); |
| 69 |
| 70 /** |
| 65 * Same as [executeCallback] but does not decrement the number of | 71 * Same as [executeCallback] but does not decrement the number of |
| 66 * callbacks this zone is waiting for (see [expectCallback]). | 72 * callbacks this zone is waiting for (see [expectCallback]). |
| 67 */ | 73 */ |
| 68 void executePeriodicCallback(void fun()); | 74 void executePeriodicCallback(void fun()); |
| 69 | 75 |
| 70 /** | 76 /** |
| 77 * Same as [executePeriodicCallback] but catches uncaught errors and gives |
| 78 * them to [handleUncaughtError]. |
| 79 */ |
| 80 void executeGuardedPeriodicCallback(void fun()); |
| 81 |
| 82 /** |
| 71 * Runs [fun] asynchronously in this zone. | 83 * Runs [fun] asynchronously in this zone. |
| 72 */ | 84 */ |
| 73 void runAsync(void fun()); | 85 void runAsync(void fun()); |
| 74 | 86 |
| 75 /** | 87 /** |
| 88 * Creates a Timer where the callback is executed in this zone. |
| 89 */ |
| 90 Timer createTimer(Duration duration, void callback()); |
| 91 |
| 92 /** |
| 93 * Creates a periodic Timer where the callback is executed in this zone. |
| 94 */ |
| 95 Timer createPeriodicTimer(Duration duration, void callback(Timer timer)); |
| 96 |
| 97 /** |
| 76 * The error zone is the one that is responsible for dealing with uncaught | 98 * The error zone is the one that is responsible for dealing with uncaught |
| 77 * errors. Errors are not allowed to cross zones with different error-zones. | 99 * errors. Errors are not allowed to cross zones with different error-zones. |
| 78 */ | 100 */ |
| 79 _Zone get _errorZone; | 101 _Zone get _errorZone; |
| 80 | 102 |
| 81 /** | 103 /** |
| 82 * Adds [child] as a child of `this`. | 104 * Adds [child] as a child of `this`. |
| 83 * | 105 * |
| 84 * This usually means that the [child] is in the asynchronous dynamic extent | 106 * This usually means that the [child] is in the asynchronous dynamic extent |
| 85 * of `this`. | 107 * of `this`. |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 * | 188 * |
| 167 * Decrements the open-callback counter and checks (after the call) if the | 189 * Decrements the open-callback counter and checks (after the call) if the |
| 168 * zone is done. | 190 * zone is done. |
| 169 */ | 191 */ |
| 170 void executeCallback(void fun()) { | 192 void executeCallback(void fun()) { |
| 171 _openCallbacks--; | 193 _openCallbacks--; |
| 172 _runInZone(fun); | 194 _runInZone(fun); |
| 173 } | 195 } |
| 174 | 196 |
| 175 /** | 197 /** |
| 198 * Same as [executeCallback] but catches uncaught errors and gives them to |
| 199 * [handleUncaughtError]. |
| 200 */ |
| 201 void executeCallbackGuarded(void fun()) { |
| 202 _openCallbacks--; |
| 203 _runGuarded(fun); |
| 204 } |
| 205 |
| 206 /** |
| 176 * Same as [executeCallback] but doesn't decrement the open-callback counter. | 207 * Same as [executeCallback] but doesn't decrement the open-callback counter. |
| 177 */ | 208 */ |
| 178 void executePeriodicCallback(void fun()) { | 209 void executePeriodicCallback(void fun()) { |
| 179 _runInZone(fun); | 210 _runInZone(fun); |
| 180 } | 211 } |
| 181 | 212 |
| 213 /** |
| 214 * Same as [executePeriodicCallback] but catches uncaught errors and gives |
| 215 * them to [handleUncaughtError]. |
| 216 */ |
| 217 void executeGuardedPeriodicCallback(void fun()) { |
| 218 _runGuarded(fun); |
| 219 } |
| 220 |
| 182 _runInZone(fun()) { | 221 _runInZone(fun()) { |
| 183 if (identical(_Zone._current, this) && _openCallbacks != 0) return fun(); | 222 if (identical(_Zone._current, this) && _openCallbacks != 0) return fun(); |
| 184 return _runGuarded(fun); | |
| 185 } | |
| 186 | 223 |
| 187 _runGuarded(void fun()) { | |
| 188 _Zone oldZone = _Zone._current; | 224 _Zone oldZone = _Zone._current; |
| 189 _Zone._current = this; | 225 _Zone._current = this; |
| 190 // While we are executing the function we don't want to have other | 226 // While we are executing the function we don't want to have other |
| 191 // synchronous calls to think that they closed the zone. By incrementing | 227 // synchronous calls to think that they closed the zone. By incrementing |
| 192 // the _openCallbacks count we make sure that their test will fail. | 228 // the _openCallbacks count we make sure that their test will fail. |
| 193 // As a side effect it will make nested calls faster since they are | 229 // As a side effect it will make nested calls faster since they are |
| 194 // (probably) in the same zone and have an _openCallbacks > 0. | 230 // (probably) in the same zone and have an _openCallbacks > 0. |
| 195 _openCallbacks++; | 231 _openCallbacks++; |
| 196 try { | 232 try { |
| 197 return fun(); | 233 return fun(); |
| 198 } finally { | 234 } finally { |
| 199 _openCallbacks--; | 235 _openCallbacks--; |
| 200 _Zone._current = oldZone; | 236 _Zone._current = oldZone; |
| 201 _checkIfDone(); | 237 _checkIfDone(); |
| 202 } | 238 } |
| 203 } | 239 } |
| 204 | 240 |
| 241 /** |
| 242 * Runs the function and catches uncaught errors. |
| 243 * |
| 244 * Uncaught errors are given to [handleUncaughtError]. |
| 245 */ |
| 246 _runGuarded(void fun()) { |
| 247 try { |
| 248 _runInZone(fun); |
| 249 } catch(e, s) { |
| 250 handleUncaughtError(_asyncError(e, s)); |
| 251 } |
| 252 } |
| 253 |
| 205 runAsync(void fun()) { | 254 runAsync(void fun()) { |
| 206 _openCallbacks++; | 255 _openCallbacks++; |
| 207 _scheduleAsyncCallback(() { | 256 _scheduleAsyncCallback(() { |
| 208 _openCallbacks--; | 257 _openCallbacks--; |
| 209 try { | 258 _runGuarded(fun); |
| 210 _runInZone(fun); | |
| 211 } catch(e, s) { | |
| 212 handleUncaughtError(_asyncError(e, s)); | |
| 213 } | |
| 214 }); | 259 }); |
| 215 } | 260 } |
| 216 | 261 |
| 262 Timer createTimer(Duration duration, void callback()) { |
| 263 return new _ZoneTimer(this, duration, callback); |
| 264 } |
| 265 |
| 266 Timer createPeriodicTimer(Duration duration, void callback(Timer timer)) { |
| 267 return new _PeriodicZoneTimer(this, duration, callback); |
| 268 } |
| 269 |
| 217 void _addChild(_Zone child) { | 270 void _addChild(_Zone child) { |
| 218 _children.add(child); | 271 _children.add(child); |
| 219 } | 272 } |
| 220 | 273 |
| 221 void _removeChild(_Zone child) { | 274 void _removeChild(_Zone child) { |
| 222 assert(!_children.isEmpty); | 275 assert(!_children.isEmpty); |
| 223 // Children are usually added and removed fifo or filo. | 276 // Children are usually added and removed fifo or filo. |
| 224 if (identical(_children.last, child)) { | 277 if (identical(_children.last, child)) { |
| 225 _children.length--; | 278 _children.length--; |
| 226 _checkIfDone(); | 279 _checkIfDone(); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 | 364 |
| 312 Future runWaitForCompletion(void fun()) { | 365 Future runWaitForCompletion(void fun()) { |
| 313 super.runWaitForCompletion(fun).whenComplete(() { | 366 super.runWaitForCompletion(fun).whenComplete(() { |
| 314 errorsController.close(); | 367 errorsController.close(); |
| 315 }); | 368 }); |
| 316 } | 369 } |
| 317 | 370 |
| 318 String toString() => "WithErrors ${super.toString()}"; | 371 String toString() => "WithErrors ${super.toString()}"; |
| 319 } | 372 } |
| 320 | 373 |
| 374 typedef void _TimerCallback(); |
| 375 |
| 376 /** |
| 377 * A [Timer] class that takes zones into account. |
| 378 */ |
| 379 class _ZoneTimer implements Timer { |
| 380 final _Zone _zone; |
| 381 final _TimerCallback _callback; |
| 382 Timer _timer; |
| 383 bool _isDone = false; |
| 384 |
| 385 _ZoneTimer(this._zone, Duration duration, this._callback) { |
| 386 _zone.expectCallback(); |
| 387 _timer = _createTimer(duration, this.run); |
| 388 } |
| 389 |
| 390 void run() { |
| 391 _isDone = true; |
| 392 _zone.executeCallbackGuarded(_callback); |
| 393 } |
| 394 |
| 395 void cancel() { |
| 396 if (!_isDone) _zone.unexpectCallback(); |
| 397 _isDone = true; |
| 398 _timer.cancel(); |
| 399 } |
| 400 } |
| 401 |
| 402 typedef void _PeriodicTimerCallback(Timer timer); |
| 403 |
| 404 /** |
| 405 * A [Timer] class for periodic callbacks that takes zones into account. |
| 406 */ |
| 407 class _PeriodicZoneTimer implements Timer { |
| 408 final _Zone _zone; |
| 409 final _PeriodicTimerCallback _callback; |
| 410 Timer _timer; |
| 411 bool _isDone = false; |
| 412 |
| 413 _PeriodicZoneTimer(this._zone, Duration duration, this._callback) { |
| 414 _zone.expectCallback(); |
| 415 _timer = _createPeriodicTimer(duration, this.run); |
| 416 } |
| 417 |
| 418 void run(Timer timer) { |
| 419 assert(identical(_timer, timer)); |
| 420 _zone.executeGuardedPeriodicCallback(() { _callback(this); }); |
| 421 } |
| 422 |
| 423 void cancel() { |
| 424 if (!_isDone) _zone.unexpectCallback(); |
| 425 _isDone = true; |
| 426 _timer.cancel(); |
| 427 } |
| 428 } |
| 429 |
| 321 Stream catchErrors(void body()) { | 430 Stream catchErrors(void body()) { |
| 322 _CatchErrorsZone catchErrorsZone = new _CatchErrorsZone(_Zone._current); | 431 _CatchErrorsZone catchErrorsZone = new _CatchErrorsZone(_Zone._current); |
| 323 catchErrorsZone.runWaitForCompletion(body); | 432 catchErrorsZone.runWaitForCompletion(body); |
| 324 return catchErrorsZone.errors; | 433 return catchErrorsZone.errors; |
| 325 } | 434 } |
| 326 | 435 |
| 327 Future waitForCompletion(void body()) { | 436 Future waitForCompletion(void body()) { |
| 328 _WaitForCompletionZone zone = new _WaitForCompletionZone(_Zone._current); | 437 _WaitForCompletionZone zone = new _WaitForCompletionZone(_Zone._current); |
| 329 return zone.runWaitForCompletion(body); | 438 return zone.runWaitForCompletion(body); |
| 330 } | 439 } |
| OLD | NEW |