OLD | NEW |
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 // |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 | 139 |
140 static bool _handlingCallbacks = false; | 140 static bool _handlingCallbacks = false; |
141 | 141 |
142 Function _callback; // Closure to call when timer fires. null if canceled. | 142 Function _callback; // Closure to call when timer fires. null if canceled. |
143 int _wakeupTime; // Expiration time. | 143 int _wakeupTime; // Expiration time. |
144 final int _milliSeconds; // Duration specified at creation. | 144 final int _milliSeconds; // Duration specified at creation. |
145 final bool _repeating; // Indicates periodic timers. | 145 final bool _repeating; // Indicates periodic timers. |
146 var _indexOrNext; // Index if part of the TimerHeap, link otherwise. | 146 var _indexOrNext; // Index if part of the TimerHeap, link otherwise. |
147 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. |
148 | 148 |
| 149 int _tick = 0; // Backing for [tick], |
| 150 |
149 // Get the next available id. We accept collisions and reordering when the | 151 // Get the next available id. We accept collisions and reordering when the |
150 // _idCount overflows and the timers expire at the same millisecond. | 152 // _idCount overflows and the timers expire at the same millisecond. |
151 static int _nextId() { | 153 static int _nextId() { |
152 var result = _idCount; | 154 var result = _idCount; |
153 _idCount = (_idCount + 1) & _ID_MASK; | 155 _idCount = (_idCount + 1) & _ID_MASK; |
154 return result; | 156 return result; |
155 } | 157 } |
156 | 158 |
157 _Timer._internal( | 159 _Timer._internal( |
158 this._callback, this._wakeupTime, this._milliSeconds, this._repeating) | 160 this._callback, this._wakeupTime, this._milliSeconds, this._repeating) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 bool get _isInHeap => _indexOrNext is int; | 192 bool get _isInHeap => _indexOrNext is int; |
191 | 193 |
192 int _compareTo(_Timer other) { | 194 int _compareTo(_Timer other) { |
193 int c = _wakeupTime - other._wakeupTime; | 195 int c = _wakeupTime - other._wakeupTime; |
194 if (c != 0) return c; | 196 if (c != 0) return c; |
195 return _id - other._id; | 197 return _id - other._id; |
196 } | 198 } |
197 | 199 |
198 bool get isActive => _callback != null; | 200 bool get isActive => _callback != null; |
199 | 201 |
| 202 int get tick => _tick; |
| 203 |
200 // Cancels a set timer. The timer is removed from the timer heap if it is a | 204 // Cancels a set timer. The timer is removed from the timer heap if it is a |
201 // non-zero timer. Zero timers are kept in the list as they need to consume | 205 // non-zero timer. Zero timers are kept in the list as they need to consume |
202 // the corresponding pending message. | 206 // the corresponding pending message. |
203 void cancel() { | 207 void cancel() { |
204 _callback = null; | 208 _callback = null; |
205 // Only heap timers are really removed. Zero timers need to consume their | 209 // Only heap timers are really removed. Zero timers need to consume their |
206 // corresponding wakeup message so they are left in the queue. | 210 // corresponding wakeup message so they are left in the queue. |
207 if (!_isInHeap) return; | 211 if (!_isInHeap) return; |
208 bool update = _heap.isFirst(this); | 212 bool update = _heap.isFirst(this); |
209 _heap.remove(this); | 213 _heap.remove(this); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 timer._indexOrNext = null; | 360 timer._indexOrNext = null; |
357 | 361 |
358 // One of the timers in the pending_timers list can cancel | 362 // One of the timers in the pending_timers list can cancel |
359 // one of the later timers which will set the callback to | 363 // one of the later timers which will set the callback to |
360 // null. Or the pending zero timer has been canceled earlier. | 364 // null. Or the pending zero timer has been canceled earlier. |
361 if (timer._callback != null) { | 365 if (timer._callback != null) { |
362 var callback = timer._callback; | 366 var callback = timer._callback; |
363 if (!timer._repeating) { | 367 if (!timer._repeating) { |
364 // Mark timer as inactive. | 368 // Mark timer as inactive. |
365 timer._callback = null; | 369 timer._callback = null; |
| 370 } else if (timer._milliSeconds > 0) { |
| 371 var ms = timer._milliSeconds; |
| 372 int overdue = |
| 373 VMLibraryHooks.timerMillisecondClock() - timer._wakeupTime; |
| 374 if (overdue > ms) { |
| 375 int missedTicks = overdue ~/ ms; |
| 376 timer._wakeupTime += missedTicks * ms; |
| 377 timer._tick += missedTicks; |
| 378 } |
366 } | 379 } |
| 380 timer._tick += 1; |
| 381 |
367 callback(timer); | 382 callback(timer); |
368 // Re-insert repeating timer if not canceled. | 383 // Re-insert repeating timer if not canceled. |
369 if (timer._repeating && (timer._callback != null)) { | 384 if (timer._repeating && (timer._callback != null)) { |
370 timer._advanceWakeupTime(); | 385 timer._advanceWakeupTime(); |
371 timer._enqueue(); | 386 timer._enqueue(); |
372 } | 387 } |
373 // Execute pending micro tasks. | 388 // Execute pending micro tasks. |
374 var immediateCallback = _removePendingImmediateCallback(); | 389 var immediateCallback = _removePendingImmediateCallback(); |
375 if (immediateCallback != null) { | 390 if (immediateCallback != null) { |
376 immediateCallback(); | 391 immediateCallback(); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 if (repeating) { | 458 if (repeating) { |
444 return new _Timer.periodic(milliSeconds, callback); | 459 return new _Timer.periodic(milliSeconds, callback); |
445 } | 460 } |
446 return new _Timer(milliSeconds, callback); | 461 return new _Timer(milliSeconds, callback); |
447 } | 462 } |
448 } | 463 } |
449 | 464 |
450 _setupHooks() { | 465 _setupHooks() { |
451 VMLibraryHooks.timerFactory = _Timer._factory; | 466 VMLibraryHooks.timerFactory = _Timer._factory; |
452 } | 467 } |
OLD | NEW |