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

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

Issue 15764003: Add Zone support for Timers. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Reupload 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/timer.dart ('k') | tests/lib/async/catch_errors10_test.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) 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
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
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
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 }
OLDNEW
« no previous file with comments | « sdk/lib/async/timer.dart ('k') | tests/lib/async/catch_errors10_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698