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

Side by Side Diff: runtime/lib/timer_impl.dart

Issue 2759973004: Fix observatory tests broken by running dartfmt. Temporarily reverted formatting for evaluate_activ… (Closed)
Patch Set: 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
« no previous file with comments | « runtime/lib/timeline.dart ('k') | runtime/lib/timer_patch.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 import 'dart:_internal' hide Symbol; 5 import 'dart:_internal' hide Symbol;
6 6
7 // Timer heap implemented as a array-based binary heap[0]. 7 // Timer heap implemented as a array-based binary heap[0].
8 // This allows for O(1) `first`, O(log(n)) `remove`/`removeFirst` and O(log(n)) 8 // This allows for O(1) `first`, O(log(n)) `remove`/`removeFirst` and O(log(n))
9 // `add`. 9 // `add`.
10 // 10 //
11 // To ensure the timers are ordered by insertion time, the _Timer class has a 11 // To ensure the timers are ordered by insertion time, the _Timer class has a
12 // `_id` field set when added to the heap. 12 // `_id` field set when added to the heap.
13 // 13 //
14 // [0] http://en.wikipedia.org/wiki/Binary_heap 14 // [0] http://en.wikipedia.org/wiki/Binary_heap
15 class _TimerHeap { 15 class _TimerHeap {
16 List<_Timer> _list; 16 List<_Timer> _list;
17 int _used = 0; 17 int _used = 0;
18 18
19 _TimerHeap([int initSize = 7]) 19 _TimerHeap([int initSize = 7]) : _list = new List<_Timer>(initSize);
20 : _list = new List<_Timer>(initSize);
21 20
22 bool get isEmpty => _used == 0; 21 bool get isEmpty => _used == 0;
23 22
24 _Timer get first => _list[0]; 23 _Timer get first => _list[0];
25 24
26 bool isFirst(_Timer timer) => timer._indexOrNext == 0; 25 bool isFirst(_Timer timer) => timer._indexOrNext == 0;
27 26
28 void add(_Timer timer) { 27 void add(_Timer timer) {
29 if (_used == _list.length) { 28 if (_used == _list.length) {
30 _resize(); 29 _resize();
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 // ids are recycled after ID_MASK enqueues or when the timer queue is empty. 132 // ids are recycled after ID_MASK enqueues or when the timer queue is empty.
134 static const _ID_MASK = 0x1fffffff; 133 static const _ID_MASK = 0x1fffffff;
135 static int _idCount = 0; 134 static int _idCount = 0;
136 135
137 static RawReceivePort _receivePort; 136 static RawReceivePort _receivePort;
138 static SendPort _sendPort; 137 static SendPort _sendPort;
139 static int _scheduledWakeupTime; 138 static int _scheduledWakeupTime;
140 139
141 static bool _handlingCallbacks = false; 140 static bool _handlingCallbacks = false;
142 141
143 Function _callback; // Closure to call when timer fires. null if canceled. 142 Function _callback; // Closure to call when timer fires. null if canceled.
144 int _wakeupTime; // Expiration time. 143 int _wakeupTime; // Expiration time.
145 final int _milliSeconds; // Duration specified at creation. 144 final int _milliSeconds; // Duration specified at creation.
146 final bool _repeating; // Indicates periodic timers. 145 final bool _repeating; // Indicates periodic timers.
147 var _indexOrNext; // Index if part of the TimerHeap, link otherwise. 146 var _indexOrNext; // Index if part of the TimerHeap, link otherwise.
148 int _id; // Incrementing id to enable sorting of timers with same expiry. 147 int _id; // Incrementing id to enable sorting of timers with same expiry.
149
150 148
151 // Get the next available id. We accept collisions and reordering when the 149 // Get the next available id. We accept collisions and reordering when the
152 // _idCount overflows and the timers expire at the same millisecond. 150 // _idCount overflows and the timers expire at the same millisecond.
153 static int _nextId() { 151 static int _nextId() {
154 var result = _idCount; 152 var result = _idCount;
155 _idCount = (_idCount + 1) & _ID_MASK; 153 _idCount = (_idCount + 1) & _ID_MASK;
156 return result; 154 return result;
157 } 155 }
158 156
157 _Timer._internal(
158 this._callback, this._wakeupTime, this._milliSeconds, this._repeating)
159 : _id = _nextId();
159 160
160 _Timer._internal(this._callback, 161 static Timer _createTimer(
161 this._wakeupTime, 162 void callback(Timer timer), int milliSeconds, bool repeating) {
162 this._milliSeconds,
163 this._repeating) : _id = _nextId();
164
165
166 static Timer _createTimer(void callback(Timer timer),
167 int milliSeconds,
168 bool repeating) {
169 // Negative timeouts are treated as if 0 timeout. 163 // Negative timeouts are treated as if 0 timeout.
170 if (milliSeconds < 0) { 164 if (milliSeconds < 0) {
171 milliSeconds = 0; 165 milliSeconds = 0;
172 } 166 }
173 // Add one because DateTime.now() is assumed to round down 167 // Add one because DateTime.now() is assumed to round down
174 // to nearest millisecond, not up, so that time + duration is before 168 // to nearest millisecond, not up, so that time + duration is before
175 // duration milliseconds from now. Using microsecond timers like 169 // duration milliseconds from now. Using microsecond timers like
176 // Stopwatch allows detecting that the timer fires early. 170 // Stopwatch allows detecting that the timer fires early.
177 int now = VMLibraryHooks.timerMillisecondClock(); 171 int now = VMLibraryHooks.timerMillisecondClock();
178 int wakeupTime = (milliSeconds == 0) ? now : (now + 1 + milliSeconds); 172 int wakeupTime = (milliSeconds == 0) ? now : (now + 1 + milliSeconds);
179 173
180 _Timer timer = new _Timer._internal(callback, 174 _Timer timer =
181 wakeupTime, 175 new _Timer._internal(callback, wakeupTime, milliSeconds, repeating);
182 milliSeconds,
183 repeating);
184 // Enqueue this newly created timer in the appropriate structure and 176 // Enqueue this newly created timer in the appropriate structure and
185 // notify if necessary. 177 // notify if necessary.
186 timer._enqueue(); 178 timer._enqueue();
187 return timer; 179 return timer;
188 } 180 }
189 181
190
191 factory _Timer(int milliSeconds, void callback(Timer timer)) { 182 factory _Timer(int milliSeconds, void callback(Timer timer)) {
192 return _createTimer(callback, milliSeconds, false); 183 return _createTimer(callback, milliSeconds, false);
193 } 184 }
194 185
195
196 factory _Timer.periodic(int milliSeconds, void callback(Timer timer)) { 186 factory _Timer.periodic(int milliSeconds, void callback(Timer timer)) {
197 return _createTimer(callback, milliSeconds, true); 187 return _createTimer(callback, milliSeconds, true);
198 } 188 }
199 189
200
201 bool get _isInHeap => _indexOrNext is int; 190 bool get _isInHeap => _indexOrNext is int;
202 191
203
204 int _compareTo(_Timer other) { 192 int _compareTo(_Timer other) {
205 int c = _wakeupTime - other._wakeupTime; 193 int c = _wakeupTime - other._wakeupTime;
206 if (c != 0) return c; 194 if (c != 0) return c;
207 return _id - other._id; 195 return _id - other._id;
208 } 196 }
209 197
210
211 bool get isActive => _callback != null; 198 bool get isActive => _callback != null;
212 199
213
214 // Cancels a set timer. The timer is removed from the timer heap if it is a 200 // Cancels a set timer. The timer is removed from the timer heap if it is a
215 // non-zero timer. Zero timers are kept in the list as they need to consume 201 // non-zero timer. Zero timers are kept in the list as they need to consume
216 // the corresponding pending message. 202 // the corresponding pending message.
217 void cancel() { 203 void cancel() {
218 _callback = null; 204 _callback = null;
219 // Only heap timers are really removed. Zero timers need to consume their 205 // Only heap timers are really removed. Zero timers need to consume their
220 // corresponding wakeup message so they are left in the queue. 206 // corresponding wakeup message so they are left in the queue.
221 if (!_isInHeap) return; 207 if (!_isInHeap) return;
222 bool update = _heap.isFirst(this); 208 bool update = _heap.isFirst(this);
223 _heap.remove(this); 209 _heap.remove(this);
224 if (update) { 210 if (update) {
225 _notifyEventHandler(); 211 _notifyEventHandler();
226 } 212 }
227 } 213 }
228 214
229
230 void _advanceWakeupTime() { 215 void _advanceWakeupTime() {
231 // Recalculate the next wakeup time. For repeating timers with a 0 timeout 216 // Recalculate the next wakeup time. For repeating timers with a 0 timeout
232 // the next wakeup time is now. 217 // the next wakeup time is now.
233 _id = _nextId(); 218 _id = _nextId();
234 if (_milliSeconds > 0) { 219 if (_milliSeconds > 0) {
235 _wakeupTime += _milliSeconds; 220 _wakeupTime += _milliSeconds;
236 } else { 221 } else {
237 _wakeupTime = VMLibraryHooks.timerMillisecondClock(); 222 _wakeupTime = VMLibraryHooks.timerMillisecondClock();
238 } 223 }
239 } 224 }
240 225
241
242 // Adds a timer to the heap or timer list. Timers with the same wakeup time 226 // Adds a timer to the heap or timer list. Timers with the same wakeup time
243 // are enqueued in order and notified in FIFO order. 227 // are enqueued in order and notified in FIFO order.
244 void _enqueue() { 228 void _enqueue() {
245 if (_milliSeconds == 0) { 229 if (_milliSeconds == 0) {
246 if (_firstZeroTimer == null) { 230 if (_firstZeroTimer == null) {
247 _lastZeroTimer = this; 231 _lastZeroTimer = this;
248 _firstZeroTimer = this; 232 _firstZeroTimer = this;
249 } else { 233 } else {
250 _lastZeroTimer._indexOrNext = this; 234 _lastZeroTimer._indexOrNext = this;
251 _lastZeroTimer = this; 235 _lastZeroTimer = this;
252 } 236 }
253 // Every zero timer gets its own event. 237 // Every zero timer gets its own event.
254 _notifyZeroHandler(); 238 _notifyZeroHandler();
255 } else { 239 } else {
256 _heap.add(this); 240 _heap.add(this);
257 if (_heap.isFirst(this)) { 241 if (_heap.isFirst(this)) {
258 _notifyEventHandler(); 242 _notifyEventHandler();
259 } 243 }
260 } 244 }
261 } 245 }
262 246
263
264 // Enqeue one message for each zero timer. To be able to distinguish from 247 // Enqeue one message for each zero timer. To be able to distinguish from
265 // EventHandler messages we send a _ZERO_EVENT instead of a _TIMEOUT_EVENT. 248 // EventHandler messages we send a _ZERO_EVENT instead of a _TIMEOUT_EVENT.
266 static void _notifyZeroHandler() { 249 static void _notifyZeroHandler() {
267 if (_sendPort == null) { 250 if (_sendPort == null) {
268 _createTimerHandler(); 251 _createTimerHandler();
269 } 252 }
270 _sendPort.send(_ZERO_EVENT); 253 _sendPort.send(_ZERO_EVENT);
271 } 254 }
272 255
273
274 // Handle the notification of a zero timer. Make sure to also execute non-zero 256 // Handle the notification of a zero timer. Make sure to also execute non-zero
275 // timers with a lower expiration time. 257 // timers with a lower expiration time.
276 static List _queueFromZeroEvent() { 258 static List _queueFromZeroEvent() {
277 var pendingTimers = new List(); 259 var pendingTimers = new List();
278 assert(_firstZeroTimer != null); 260 assert(_firstZeroTimer != null);
279 // Collect pending timers from the timer heap that have an expiration prior 261 // Collect pending timers from the timer heap that have an expiration prior
280 // to the currently notified zero timer. 262 // to the currently notified zero timer.
281 var timer; 263 var timer;
282 while (!_heap.isEmpty && (_heap.first._compareTo(_firstZeroTimer) < 0)) { 264 while (!_heap.isEmpty && (_heap.first._compareTo(_firstZeroTimer) < 0)) {
283 timer = _heap.removeFirst(); 265 timer = _heap.removeFirst();
284 pendingTimers.add(timer); 266 pendingTimers.add(timer);
285 } 267 }
286 // Append the first zero timer to the pending timers. 268 // Append the first zero timer to the pending timers.
287 timer = _firstZeroTimer; 269 timer = _firstZeroTimer;
288 _firstZeroTimer = timer._indexOrNext; 270 _firstZeroTimer = timer._indexOrNext;
289 timer._indexOrNext = null; 271 timer._indexOrNext = null;
290 pendingTimers.add(timer); 272 pendingTimers.add(timer);
291 return pendingTimers; 273 return pendingTimers;
292 } 274 }
293 275
294
295 static void _notifyEventHandler() { 276 static void _notifyEventHandler() {
296 if (_handlingCallbacks) { 277 if (_handlingCallbacks) {
297 // While we are already handling callbacks we will not notify the event 278 // While we are already handling callbacks we will not notify the event
298 // handler. _handleTimeout will call _notifyEventHandler once all pending 279 // handler. _handleTimeout will call _notifyEventHandler once all pending
299 // timers are processed. 280 // timers are processed.
300 return; 281 return;
301 } 282 }
302 283
303 // If there are no pending timers. Close down the receive port. 284 // If there are no pending timers. Close down the receive port.
304 if ((_firstZeroTimer == null) && _heap.isEmpty) { 285 if ((_firstZeroTimer == null) && _heap.isEmpty) {
(...skipping 12 matching lines...) Expand all
317 298
318 // Only send a message if the requested wakeup time differs from the 299 // Only send a message if the requested wakeup time differs from the
319 // already scheduled wakeup time. 300 // already scheduled wakeup time.
320 var wakeupTime = _heap.first._wakeupTime; 301 var wakeupTime = _heap.first._wakeupTime;
321 if ((_scheduledWakeupTime == null) || 302 if ((_scheduledWakeupTime == null) ||
322 (wakeupTime != _scheduledWakeupTime)) { 303 (wakeupTime != _scheduledWakeupTime)) {
323 _scheduleWakeup(wakeupTime); 304 _scheduleWakeup(wakeupTime);
324 } 305 }
325 } 306 }
326 307
327
328 static List _queueFromTimeoutEvent() { 308 static List _queueFromTimeoutEvent() {
329 var pendingTimers = new List(); 309 var pendingTimers = new List();
330 if (_firstZeroTimer != null) { 310 if (_firstZeroTimer != null) {
331 // Collect pending timers from the timer heap that have an expiration 311 // Collect pending timers from the timer heap that have an expiration
332 // prior to the next zero timer. 312 // prior to the next zero timer.
333 // By definition the first zero timer has been scheduled before the 313 // By definition the first zero timer has been scheduled before the
334 // current time, meaning all timers which are "less than" the first zero 314 // current time, meaning all timers which are "less than" the first zero
335 // timer are expired. The first zero timer will be dispatched when its 315 // timer are expired. The first zero timer will be dispatched when its
336 // corresponding message is delivered. 316 // corresponding message is delivered.
337 var timer; 317 var timer;
338 while (!_heap.isEmpty && (_heap.first._compareTo(_firstZeroTimer) < 0)) { 318 while (!_heap.isEmpty && (_heap.first._compareTo(_firstZeroTimer) < 0)) {
339 timer = _heap.removeFirst(); 319 timer = _heap.removeFirst();
340 pendingTimers.add(timer); 320 pendingTimers.add(timer);
341 } 321 }
342 } else { 322 } else {
343 // Collect pending timers from the timer heap which have expired at this 323 // Collect pending timers from the timer heap which have expired at this
344 // time. 324 // time.
345 var currentTime = VMLibraryHooks.timerMillisecondClock(); 325 var currentTime = VMLibraryHooks.timerMillisecondClock();
346 var timer; 326 var timer;
347 while (!_heap.isEmpty && (_heap.first._wakeupTime <= currentTime)) { 327 while (!_heap.isEmpty && (_heap.first._wakeupTime <= currentTime)) {
348 timer = _heap.removeFirst(); 328 timer = _heap.removeFirst();
349 pendingTimers.add(timer); 329 pendingTimers.add(timer);
350 } 330 }
351 } 331 }
352 return pendingTimers; 332 return pendingTimers;
353 } 333 }
354 334
355
356 static void _runTimers(List pendingTimers) { 335 static void _runTimers(List pendingTimers) {
357 // If there are no pending timers currently reset the id space before we 336 // If there are no pending timers currently reset the id space before we
358 // have a chance to enqueue new timers. 337 // have a chance to enqueue new timers.
359 if (_heap.isEmpty && (_firstZeroTimer == null)) { 338 if (_heap.isEmpty && (_firstZeroTimer == null)) {
360 _idCount = 0; 339 _idCount = 0;
361 } 340 }
362 341
363 // Fast exit if no pending timers. 342 // Fast exit if no pending timers.
364 if (pendingTimers.length == 0) { 343 if (pendingTimers.length == 0) {
365 return; 344 return;
(...skipping 29 matching lines...) Expand all
395 if (immediateCallback != null) { 374 if (immediateCallback != null) {
396 immediateCallback(); 375 immediateCallback();
397 } 376 }
398 } 377 }
399 } 378 }
400 } finally { 379 } finally {
401 _handlingCallbacks = false; 380 _handlingCallbacks = false;
402 } 381 }
403 } 382 }
404 383
405
406 static void _handleMessage(msg) { 384 static void _handleMessage(msg) {
407 var pendingTimers; 385 var pendingTimers;
408 if (msg == _ZERO_EVENT) { 386 if (msg == _ZERO_EVENT) {
409 pendingTimers = _queueFromZeroEvent(); 387 pendingTimers = _queueFromZeroEvent();
410 assert(pendingTimers.length > 0); 388 assert(pendingTimers.length > 0);
411 } else { 389 } else {
412 assert(msg == _TIMEOUT_EVENT); 390 assert(msg == _TIMEOUT_EVENT);
413 _scheduledWakeupTime = null; // Consumed the last scheduled wakeup now. 391 _scheduledWakeupTime = null; // Consumed the last scheduled wakeup now.
414 pendingTimers = _queueFromTimeoutEvent(); 392 pendingTimers = _queueFromTimeoutEvent();
415 } 393 }
416 _runTimers(pendingTimers); 394 _runTimers(pendingTimers);
417 // Notify the event handler or shutdown the port if no more pending 395 // Notify the event handler or shutdown the port if no more pending
418 // timers are present. 396 // timers are present.
419 _notifyEventHandler(); 397 _notifyEventHandler();
420 } 398 }
421 399
422
423 // Tell the event handler to wake this isolate at a specific time. 400 // Tell the event handler to wake this isolate at a specific time.
424 static void _scheduleWakeup(int wakeupTime) { 401 static void _scheduleWakeup(int wakeupTime) {
425 if (_sendPort == null) { 402 if (_sendPort == null) {
426 _createTimerHandler(); 403 _createTimerHandler();
427 } 404 }
428 VMLibraryHooks.eventHandlerSendData(null, _sendPort, wakeupTime); 405 VMLibraryHooks.eventHandlerSendData(null, _sendPort, wakeupTime);
429 _scheduledWakeupTime = wakeupTime; 406 _scheduledWakeupTime = wakeupTime;
430 } 407 }
431 408
432
433 // Cancel pending wakeups in the event handler. 409 // Cancel pending wakeups in the event handler.
434 static void _cancelWakeup() { 410 static void _cancelWakeup() {
435 assert(_sendPort != null); 411 assert(_sendPort != null);
436 VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER); 412 VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER);
437 _scheduledWakeupTime = null; 413 _scheduledWakeupTime = null;
438 } 414 }
439 415
440
441 // Create a receive port and register a message handler for the timer 416 // Create a receive port and register a message handler for the timer
442 // events. 417 // events.
443 static void _createTimerHandler() { 418 static void _createTimerHandler() {
444 assert(_receivePort == null); 419 assert(_receivePort == null);
445 assert(_sendPort == null); 420 assert(_sendPort == null);
446 _receivePort = new RawReceivePort(_handleMessage); 421 _receivePort = new RawReceivePort(_handleMessage);
447 _sendPort = _receivePort.sendPort; 422 _sendPort = _receivePort.sendPort;
448 _scheduledWakeupTime = null; 423 _scheduledWakeupTime = null;
449 } 424 }
450 425
451
452 static void _shutdownTimerHandler() { 426 static void _shutdownTimerHandler() {
453 _receivePort.close(); 427 _receivePort.close();
454 _receivePort = null; 428 _receivePort = null;
455 _sendPort = null; 429 _sendPort = null;
456 _scheduledWakeupTime = null; 430 _scheduledWakeupTime = null;
457 } 431 }
458 432
459
460 // The Timer factory registered with the dart:async library by the embedder. 433 // The Timer factory registered with the dart:async library by the embedder.
461 static Timer _factory(int milliSeconds, 434 static Timer _factory(
462 void callback(Timer timer), 435 int milliSeconds, void callback(Timer timer), bool repeating) {
463 bool repeating) {
464 if (repeating) { 436 if (repeating) {
465 return new _Timer.periodic(milliSeconds, callback); 437 return new _Timer.periodic(milliSeconds, callback);
466 } 438 }
467 return new _Timer(milliSeconds, callback); 439 return new _Timer(milliSeconds, callback);
468 } 440 }
469 } 441 }
470 442
471
472 _setupHooks() { 443 _setupHooks() {
473 VMLibraryHooks.timerFactory = _Timer._factory; 444 VMLibraryHooks.timerFactory = _Timer._factory;
474 } 445 }
OLDNEW
« no previous file with comments | « runtime/lib/timeline.dart ('k') | runtime/lib/timer_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698