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.
|
+} |