Chromium Code Reviews| Index: sdk/lib/async/event_loop.dart |
| diff --git a/sdk/lib/async/event_loop.dart b/sdk/lib/async/event_loop.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a1ecdc9b40877f16561c76e0e4c59220154c39b0 |
| --- /dev/null |
| +++ b/sdk/lib/async/event_loop.dart |
| @@ -0,0 +1,73 @@ |
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +part of dart.async; |
| + |
| +typedef void _AsyncCallback(); |
| + |
| +bool _callbacksAreEnqueued = false; |
| +List<_AsyncCallback> _asyncCallbacks = <_AsyncCallback>[]; |
| + |
| +void _asyncRunCallback() { |
| + // As long as we are iterating over the registered callbacks we don't |
| + // unset the [_callbacksAreEnqueued] boolean. |
| + while (!_asyncCallbacks.isEmpty) { |
| + List callbacks = _asyncCallbacks; |
| + // Create a new list, to avoid that the we grow too much if the callbacks |
| + // add new callbacks themselves. |
| + _asyncCallbacks = <_AsyncCallback>[]; |
|
Lasse Reichstein Nielsen
2013/03/04 09:23:24
Or use a ListQueue for the callbacks queue. Then y
floitsch
2013/03/04 17:26:05
The async library doesn't include the collection l
|
| + for (int i = 0; i < callbacks.length; i++) { |
|
Lasse Reichstein Nielsen
2013/03/04 09:23:24
Should we avoid running too much in the same event
floitsch
2013/03/04 17:26:05
No. runAsync guarantees to run before all events.
|
| + Function callback = callbacks[i]; |
| + callbacks[i] = null; |
| + try { |
| + callback(); |
| + } catch (e) { |
|
Lasse Reichstein Nielsen
2013/03/04 09:23:24
If you keep using the same ListQueue, you don't ha
floitsch
2013/03/04 17:26:05
I considered ListQueues, but decided against them
|
| + List remainingCallbacks = |
| + _asyncCallbacks.getRange(i + 1, _asyncCallbacks.length - i + 1); |
| + List newCallbacks = _asyncCallbacks; |
| + _asyncCallbacks = []; |
|
Lasse Reichstein Nielsen
2013/03/04 09:23:24
Missing type parameter.
floitsch
2013/03/04 17:26:05
Done.
|
| + _asyncCallbacks.addAll(remainingCallbacks); |
| + _asyncCallbacks.addAll(newCallbacks); |
| + _AsyncRun._enqueueImmediate(_asyncRunCallback); |
| + throw; |
| + } |
| + } |
| + } |
| + // Any new callback must register a callback function now. |
| + _callbacksAreEnqueued = false; |
| +} |
| + |
| +/** |
| + * Runs the given [callback] asynchronously. |
| + * |
| + * Callbacks register through this function are always executed in order and |
| + * are guaranteed to run before other asynchronous events (like [Timer] events, |
| + * or DOM events). |
| + * |
| + * Warning: it is possible to starve the DOM by registering asynchronous |
| + * callbacks through this method. For example the following program will |
| + * run the callbacks without ever giving the Timer callback a chance to execute: |
| + * |
| + * Timer.run(() { print("executed"); }); // Will never be executed; |
| + * foo() { |
| + * asyncRun(foo); // Schedules [foo] in front of other events. |
| + * } |
| + * main() { |
| + * foo(); |
| + * } |
| + */ |
| +void runAsync(void callback()) { |
| + // Optimizing a group of Timer.run callbacks to be executed in the |
| + // same Timer callback. |
| + _asyncCallbacks.add(callback); |
| + if (!_callbacksAreEnqueued) { |
| + _AsyncRun._enqueueImmediate(_asyncRunCallback); |
| + _callbacksAreEnqueued = true; |
| + } |
| +} |
| + |
| +class _AsyncRun { |
| + /** Enqueues the given callback before any other event in the event-loop. */ |
| + external static void _enqueueImmediate(void callback()); |
|
Lasse Reichstein Nielsen
2013/03/04 09:23:24
Why this class? You should be able to patch top-le
floitsch
2013/03/04 17:26:05
I tried, but I couldn't get it to work.
|
| +} |