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..54e05f0e3d27a91d0d49b0bdcb3f7c4d391cee07 |
--- /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 |
siva
2013/03/07 02:39:17
This comment does not read well.
floitsch
2013/03/08 20:04:41
done.
|
+ // add new callbacks themselves. |
+ _asyncCallbacks = <_AsyncCallback>[]; |
+ for (int i = 0; i < callbacks.length; i++) { |
+ Function callback = callbacks[i]; |
+ callbacks[i] = null; |
+ try { |
+ callback(); |
+ } catch (e) { |
+ List remainingCallbacks = |
+ _asyncCallbacks.getRange(i + 1, _asyncCallbacks.length - i + 1); |
siva
2013/03/07 02:39:17
shouldn't this be:
List remainingCallbacks = callb
floitsch
2013/03/08 20:04:41
Done.
|
+ List newCallbacks = _asyncCallbacks; |
+ _asyncCallbacks = <_AsyncCallback>[]; |
+ _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 |
siva
2013/03/07 02:39:17
registered
floitsch
2013/03/08 20:04:41
Done.
|
+ * 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()); |
+} |