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

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/lib/async/schedule_microtask.dart

Issue 2698353003: unfork DDC's copy of most SDK libraries (Closed)
Patch Set: revert core_patch Created 3 years, 9 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
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart.async;
6
7 typedef void _AsyncCallback();
8
9 class _AsyncCallbackEntry {
10 final _AsyncCallback callback;
11 _AsyncCallbackEntry next;
12 _AsyncCallbackEntry(this.callback);
13 }
14
15 /** Head of single linked list of pending callbacks. */
16 _AsyncCallbackEntry _nextCallback;
17 /** Tail of single linked list of pending callbacks. */
18 _AsyncCallbackEntry _lastCallback;
19 /**
20 * Tail of priority callbacks added by the currently executing callback.
21 *
22 * Priority callbacks are put at the beginning of the
23 * callback queue, so that if one callback schedules more than one
24 * priority callback, they are still enqueued in scheduling order.
25 */
26 _AsyncCallbackEntry _lastPriorityCallback;
27 /**
28 * Whether we are currently inside the callback loop.
29 *
30 * If we are inside the loop, we never need to schedule the loop,
31 * even if adding a first element.
32 */
33 bool _isInCallbackLoop = false;
34
35 void _microtaskLoop() {
36 while (_nextCallback != null) {
37 _lastPriorityCallback = null;
38 _AsyncCallbackEntry entry = _nextCallback;
39 _nextCallback = entry.next;
40 if (_nextCallback == null) _lastCallback = null;
41 (entry.callback)();
42 }
43 }
44
45 void _startMicrotaskLoop() {
46 _isInCallbackLoop = true;
47 try {
48 // Moved to separate function because try-finally prevents
49 // good optimization.
50 _microtaskLoop();
51 } finally {
52 _lastPriorityCallback = null;
53 _isInCallbackLoop = false;
54 if (_nextCallback != null) {
55 _AsyncRun._scheduleImmediate(_startMicrotaskLoop);
56 }
57 }
58 }
59
60 /**
61 * Schedules a callback to be called as a microtask.
62 *
63 * The microtask is called after all other currently scheduled
64 * microtasks, but as part of the current system event.
65 */
66 void _scheduleAsyncCallback(_AsyncCallback callback) {
67 _AsyncCallbackEntry newEntry = new _AsyncCallbackEntry(callback);
68 if (_nextCallback == null) {
69 _nextCallback = _lastCallback = newEntry;
70 if (!_isInCallbackLoop) {
71 _AsyncRun._scheduleImmediate(_startMicrotaskLoop);
72 }
73 } else {
74 _lastCallback.next = newEntry;
75 _lastCallback = newEntry;
76 }
77 }
78
79 /**
80 * Schedules a callback to be called before all other currently scheduled ones.
81 *
82 * This callback takes priority over existing scheduled callbacks.
83 * It is only used internally to give higher priority to error reporting.
84 *
85 * Is always run in the root zone.
86 */
87 void _schedulePriorityAsyncCallback(_AsyncCallback callback) {
88 if (_nextCallback == null) {
89 _scheduleAsyncCallback(callback);
90 _lastPriorityCallback = _lastCallback;
91 return;
92 }
93 _AsyncCallbackEntry entry = new _AsyncCallbackEntry(callback);
94 if (_lastPriorityCallback == null) {
95 entry.next = _nextCallback;
96 _nextCallback = _lastPriorityCallback = entry;
97 } else {
98 entry.next = _lastPriorityCallback.next;
99 _lastPriorityCallback.next = entry;
100 _lastPriorityCallback = entry;
101 if (entry.next == null) {
102 _lastCallback = entry;
103 }
104 }
105 }
106
107 /**
108 * Runs a function asynchronously.
109 *
110 * Callbacks registered through this function are always executed in order and
111 * are guaranteed to run before other asynchronous events (like [Timer] events,
112 * or DOM events).
113 *
114 * **Warning:** it is possible to starve the DOM by registering asynchronous
115 * callbacks through this method. For example the following program runs
116 * the callbacks without ever giving the Timer callback a chance to execute:
117 *
118 * main() {
119 * Timer.run(() { print("executed"); }); // Will never be executed.
120 * foo() {
121 * scheduleMicrotask(foo); // Schedules [foo] in front of other events.
122 * }
123 * foo();
124 * }
125 *
126 * ## Other resources
127 *
128 * * [The Event Loop and Dart](https://www.dartlang.org/articles/event-loop/):
129 * Learn how Dart handles the event queue and microtask queue, so you can write
130 * better asynchronous code with fewer surprises.
131 */
132 void scheduleMicrotask(void callback()) {
133 _Zone currentZone = Zone.current;
134 if (identical(_ROOT_ZONE, currentZone)) {
135 // No need to bind the callback. We know that the root's scheduleMicrotask
136 // will be invoked in the root zone.
137 _rootScheduleMicrotask(null, null, _ROOT_ZONE, callback);
138 return;
139 }
140 _ZoneFunction implementation = currentZone._scheduleMicrotask;
141 if (identical(_ROOT_ZONE, implementation.zone) &&
142 _ROOT_ZONE.inSameErrorZone(currentZone)) {
143 _rootScheduleMicrotask(null, null, currentZone,
144 currentZone.registerCallback(callback));
145 return;
146 }
147 Zone.current.scheduleMicrotask(
148 Zone.current.bindCallback(callback, runGuarded: true));
149 }
150
151 class _AsyncRun {
152 /** Schedule the given callback before any other event in the event-loop. */
153 external static void _scheduleImmediate(void callback());
154 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/tool/input_sdk/lib/async/future_impl.dart ('k') | pkg/dev_compiler/tool/input_sdk/lib/async/stream.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698