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 | |
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 |
159 _Timer._internal( | 157 _Timer._internal( |
160 this._callback, this._wakeupTime, this._milliSeconds, this._repeating) | 158 this._callback, this._wakeupTime, this._milliSeconds, this._repeating) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 bool get _isInHeap => _indexOrNext is int; | 190 bool get _isInHeap => _indexOrNext is int; |
193 | 191 |
194 int _compareTo(_Timer other) { | 192 int _compareTo(_Timer other) { |
195 int c = _wakeupTime - other._wakeupTime; | 193 int c = _wakeupTime - other._wakeupTime; |
196 if (c != 0) return c; | 194 if (c != 0) return c; |
197 return _id - other._id; | 195 return _id - other._id; |
198 } | 196 } |
199 | 197 |
200 bool get isActive => _callback != null; | 198 bool get isActive => _callback != null; |
201 | 199 |
202 int get tick => _tick; | |
203 | |
204 // 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 |
205 // 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 |
206 // the corresponding pending message. | 202 // the corresponding pending message. |
207 void cancel() { | 203 void cancel() { |
208 _callback = null; | 204 _callback = null; |
209 // 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 |
210 // corresponding wakeup message so they are left in the queue. | 206 // corresponding wakeup message so they are left in the queue. |
211 if (!_isInHeap) return; | 207 if (!_isInHeap) return; |
212 bool update = _heap.isFirst(this); | 208 bool update = _heap.isFirst(this); |
213 _heap.remove(this); | 209 _heap.remove(this); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 timer._indexOrNext = null; | 356 timer._indexOrNext = null; |
361 | 357 |
362 // One of the timers in the pending_timers list can cancel | 358 // One of the timers in the pending_timers list can cancel |
363 // one of the later timers which will set the callback to | 359 // one of the later timers which will set the callback to |
364 // null. Or the pending zero timer has been canceled earlier. | 360 // null. Or the pending zero timer has been canceled earlier. |
365 if (timer._callback != null) { | 361 if (timer._callback != null) { |
366 var callback = timer._callback; | 362 var callback = timer._callback; |
367 if (!timer._repeating) { | 363 if (!timer._repeating) { |
368 // Mark timer as inactive. | 364 // Mark timer as inactive. |
369 timer._callback = null; | 365 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 } | |
379 } | 366 } |
380 timer._tick += 1; | |
381 | |
382 callback(timer); | 367 callback(timer); |
383 // Re-insert repeating timer if not canceled. | 368 // Re-insert repeating timer if not canceled. |
384 if (timer._repeating && (timer._callback != null)) { | 369 if (timer._repeating && (timer._callback != null)) { |
385 timer._advanceWakeupTime(); | 370 timer._advanceWakeupTime(); |
386 timer._enqueue(); | 371 timer._enqueue(); |
387 } | 372 } |
388 // Execute pending micro tasks. | 373 // Execute pending micro tasks. |
389 var immediateCallback = _removePendingImmediateCallback(); | 374 var immediateCallback = _removePendingImmediateCallback(); |
390 if (immediateCallback != null) { | 375 if (immediateCallback != null) { |
391 immediateCallback(); | 376 immediateCallback(); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 if (repeating) { | 443 if (repeating) { |
459 return new _Timer.periodic(milliSeconds, callback); | 444 return new _Timer.periodic(milliSeconds, callback); |
460 } | 445 } |
461 return new _Timer(milliSeconds, callback); | 446 return new _Timer(milliSeconds, callback); |
462 } | 447 } |
463 } | 448 } |
464 | 449 |
465 _setupHooks() { | 450 _setupHooks() { |
466 VMLibraryHooks.timerFactory = _Timer._factory; | 451 VMLibraryHooks.timerFactory = _Timer._factory; |
467 } | 452 } |
OLD | NEW |