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

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

Issue 971193002: - Make sure we schedule another wakeup when handling a timeout (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | 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 // Timer heap implemented as a array-based binary heap[0]. 5 // Timer heap implemented as a array-based binary heap[0].
6 // This allows for O(1) `first`, O(log(n)) `remove`/`removeFirst` and O(log(n)) 6 // This allows for O(1) `first`, O(log(n)) `remove`/`removeFirst` and O(log(n))
7 // `add`. 7 // `add`.
8 // 8 //
9 // To ensure the timers are ordered by insertion time, the _Timer class has a 9 // To ensure the timers are ordered by insertion time, the _Timer class has a
10 // `_id` field set when added to the heap. 10 // `_id` field set when added to the heap.
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 Timer _rightChild(_Timer timer) => 108 Timer _rightChild(_Timer timer) =>
109 _list[_rightChildIndex(timer._indexOrNext)]; 109 _list[_rightChildIndex(timer._indexOrNext)];
110 110
111 static int _parentIndex(int index) => (index - 1) ~/ 2; 111 static int _parentIndex(int index) => (index - 1) ~/ 2;
112 static int _leftChildIndex(int index) => 2 * index + 1; 112 static int _leftChildIndex(int index) => 2 * index + 1;
113 static int _rightChildIndex(int index) => 2 * index + 2; 113 static int _rightChildIndex(int index) => 2 * index + 2;
114 } 114 }
115 115
116 class _Timer implements Timer { 116 class _Timer implements Timer {
117 // Cancels the timer in the event handler. 117 // Cancels the timer in the event handler.
118 static const int _NO_TIMER = -1; 118 static const _NO_TIMER = -1;
119 119
120 // We distinguish what kind of message arrived based on the value being sent. 120 // We distinguish what kind of message arrived based on the value being sent.
121 static const _ZERO_EVENT = 1; 121 static const _ZERO_EVENT = 1;
122 static const _TIMEOUT_EVENT = null; 122 static const _TIMEOUT_EVENT = null;
123 123
124 // Timers are ordered by wakeup time. Timers with a timeout value of > 0 do 124 // Timers are ordered by wakeup time. Timers with a timeout value of > 0 do
125 // end up on the TimerHeap. Timers with a timeout of 0 are queued in a list. 125 // end up on the TimerHeap. Timers with a timeout of 0 are queued in a list.
126 static _TimerHeap _heap = new _TimerHeap(); 126 static _TimerHeap _heap = new _TimerHeap();
127 static _Timer _firstZeroTimer; 127 static _Timer _firstZeroTimer;
128 static _Timer _lastZeroTimer; 128 static _Timer _lastZeroTimer;
129 129
130 // We use an id to be able to sort timers with the same expiration time. 130 // We use an id to be able to sort timers with the same expiration time.
131 // ids are recycled after ID_MASK enqueues or when the timer queue is empty. 131 // ids are recycled after ID_MASK enqueues or when the timer queue is empty.
132 static int _ID_MASK = 0x1fffffff; 132 static const _ID_MASK = 0x1fffffff;
133 static int _idCount = 0; 133 static int _idCount = 0;
134 134
135 static RawReceivePort _receivePort; 135 static RawReceivePort _receivePort;
136 static SendPort _sendPort; 136 static SendPort _sendPort;
137 static int _scheduledWakeupTime; 137 static int _scheduledWakeupTime;
138 138
139 static bool _handlingCallbacks = false; 139 static bool _handlingCallbacks = false;
140 140
141 Function _callback; // Closure to call when timer fires. null if canceled. 141 Function _callback; // Closure to call when timer fires. null if canceled.
142 int _wakeupTime; // Expiration time. 142 int _wakeupTime; // Expiration time.
143 int _milliSeconds; // Duration specified at creation. 143 int _milliSeconds; // Duration specified at creation.
144 bool _repeating; // Indicates periodic timers. 144 bool _repeating; // Indicates periodic timers.
koda 2015/03/03 06:49:20 final
145 var _indexOrNext; // Index if part of the TimerHeap, link otherwise. 145 var _indexOrNext; // Index if part of the TimerHeap, link otherwise.
146 int _id; // Incrementing id to enable sorting of timers with same expiry. 146 int _id; // Incrementing id to enable sorting of timers with same expiry.
koda 2015/03/03 06:49:20 final
147 147
148 // Get the next available id. We accept collisions and reordering when the 148 // Get the next available id. We accept collisions and reordering when the
149 // _idCount overflows and the timers expire at the same millisecond. 149 // _idCount overflows and the timers expire at the same millisecond.
150 static int _nextId() { 150 static int _nextId() {
151 var result = _idCount; 151 var result = _idCount;
152 _idCount = (_idCount + 1) & _ID_MASK; 152 _idCount = (_idCount + 1) & _ID_MASK;
153 return result; 153 return result;
154 } 154 }
155 155
156 _Timer._internal(this._callback, 156 _Timer._internal(this._callback,
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 if ((_firstZeroTimer == null) && _heap.isEmpty) { 291 if ((_firstZeroTimer == null) && _heap.isEmpty) {
292 // No pending timers: Close the receive port and let the event handler 292 // No pending timers: Close the receive port and let the event handler
293 // know. 293 // know.
294 if (_sendPort != null) { 294 if (_sendPort != null) {
295 VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER); 295 VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER);
296 _shutdownTimerHandler(); 296 _shutdownTimerHandler();
297 } 297 }
298 return; 298 return;
299 } else if (_heap.isEmpty) { 299 } else if (_heap.isEmpty) {
300 // Only zero timers are left. Cancel any scheduled wakeups. 300 // Only zero timers are left. Cancel any scheduled wakeups.
301 VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER); 301 VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER);
koda 2015/03/03 06:49:20 Shouldn't you also assign null to _scheduledWakeup
302 return; 302 return;
303 } 303 }
304 304
305 // Only send a message if the requested wakeup time differs from the 305 // Only send a message if the requested wakeup time differs from the
306 // already scheduled wakeup time. 306 // already scheduled wakeup time.
307 var wakeupTime = _heap.first._wakeupTime; 307 var wakeupTime = _heap.first._wakeupTime;
308 if ((_scheduledWakeupTime == null) || 308 if ((_scheduledWakeupTime == null) ||
309 (wakeupTime != _scheduledWakeupTime)) { 309 (wakeupTime != _scheduledWakeupTime)) {
310 if (_sendPort == null) { 310 if (_sendPort == null) {
311 // Create a receive port and register a message handler for the timer 311 // Create a receive port and register a message handler for the timer
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 395
396 // Creates a receive port and registers an empty handler on that port. Just 396 // Creates a receive port and registers an empty handler on that port. Just
397 // the triggering of the event loop will ensure that timers are executed. 397 // the triggering of the event loop will ensure that timers are executed.
398 static void _handleMessage(msg) { 398 static void _handleMessage(msg) {
399 var pendingTimers; 399 var pendingTimers;
400 if (msg == _ZERO_EVENT) { 400 if (msg == _ZERO_EVENT) {
401 pendingTimers = _queueFromZeroEvent(); 401 pendingTimers = _queueFromZeroEvent();
402 assert(pendingTimers.length > 0); 402 assert(pendingTimers.length > 0);
403 } else { 403 } else {
404 assert(msg == _TIMEOUT_EVENT); 404 assert(msg == _TIMEOUT_EVENT);
405 _scheduledWakeupTime = null; // Consumed the last scheduled wakeup now.
405 pendingTimers = _queueFromTimeoutEvent(); 406 pendingTimers = _queueFromTimeoutEvent();
406 } 407 }
407 _runTimers(pendingTimers); 408 _runTimers(pendingTimers);
408 } 409 }
409 410
410 static void _createTimerHandler() { 411 static void _createTimerHandler() {
411 assert(_receivePort == null); 412 assert(_receivePort == null);
412 assert(_sendPort == null); 413 assert(_sendPort == null);
413 _receivePort = new RawReceivePort(_handleMessage); 414 _receivePort = new RawReceivePort(_handleMessage);
414 _sendPort = _receivePort.sendPort; 415 _sendPort = _receivePort.sendPort;
(...skipping 14 matching lines...) Expand all
429 if (repeating) { 430 if (repeating) {
430 return new _Timer.periodic(milliSeconds, callback); 431 return new _Timer.periodic(milliSeconds, callback);
431 } 432 }
432 return new _Timer(milliSeconds, callback); 433 return new _Timer(milliSeconds, callback);
433 } 434 }
434 } 435 }
435 436
436 _setupHooks() { 437 _setupHooks() {
437 VMLibraryHooks.timerFactory = _Timer._factory; 438 VMLibraryHooks.timerFactory = _Timer._factory;
438 } 439 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698