Index: sdk/lib/io/timer_impl.dart |
=================================================================== |
--- sdk/lib/io/timer_impl.dart (revision 42999) |
+++ sdk/lib/io/timer_impl.dart (working copy) |
@@ -132,6 +132,10 @@ |
static RawReceivePort _receivePort; |
static SendPort _sendPort; |
static int _scheduledWakeupTime; |
+ // Keep track whether at least one message is pending in the event loop. This |
+ // way we do not have to notify for every pending _firstZeroTimer. |
+ static var _messagePending = false; |
+ |
static bool _handlingCallbacks = false; |
Function _callback; // Closure to call when timer fires. null if canceled. |
@@ -255,7 +259,7 @@ |
return; |
} |
- if (_firstZeroTimer == null && _heap.isEmpty) { |
+ if ((_firstZeroTimer == null) && _heap.isEmpty) { |
// No pending timers: Close the receive port and let the event handler |
// know. |
if (_receivePort != null) { |
@@ -269,7 +273,10 @@ |
_createTimerHandler(); |
} |
if (_firstZeroTimer != null) { |
- _sendPort.send(null); |
+ if (!_messagePending) { |
+ _sendPort.send(null); |
+ _messagePending = true; // Reset when the port receives a message. |
+ } |
} else { |
var wakeupTime = _heap.first._wakeupTime; |
if ((_scheduledWakeupTime == null) || |
@@ -282,56 +289,71 @@ |
} |
static void _handleTimeout(pendingImmediateCallback) { |
- int currentTime = new DateTime.now().millisecondsSinceEpoch; |
+ // Fast exit if no timers have been scheduled. |
+ if (_heap.isEmpty && (_firstZeroTimer == null)) { |
Søren Gjesse
2015/01/20 15:36:27
maybe assert(_receivePort == null)
Ivan Posva
2015/01/20 16:01:17
Done.
|
+ return; |
+ } |
+ |
// Collect all pending timers. |
var head = null; |
var tail = null; |
- // Keep track of the lowest wakeup times for both the list and heap. If |
- // the respective queue is empty move its time beyond the current time. |
- var heapTime = _heap.isEmpty ? |
- (currentTime + 1) : _heap.first._wakeupTime; |
- var listTime = (_firstZeroTimer == null) ? |
- (currentTime + 1) : _firstZeroTimer._wakeupTime; |
+ if (_heap.isEmpty) { |
+ // Only immediate timers are scheduled. Take over the whole list as is. |
+ assert(_firstZeroTimer != null); |
+ assert(_lastZeroTimer != null); |
+ head = _firstZeroTimer; |
+ tail = _lastZeroTimer; |
+ _firstZeroTimer = null; |
+ _lastZeroTimer = null; |
+ } else { |
+ assert(!_heap.isEmpty); |
zra
2015/01/20 15:23:34
Why is this assert needed?
Ivan Posva
2015/01/20 16:01:17
It is more of a documentation and making sure the
|
+ // Keep track of the lowest wakeup times for both the list and heap. If |
+ // the respective queue is empty move its time beyond the current time. |
+ var currentTime = new DateTime.now().millisecondsSinceEpoch; |
+ var heapTime = _heap.first._wakeupTime; |
+ var listTime = (_firstZeroTimer == null) ? |
+ (currentTime + 1) : _firstZeroTimer._wakeupTime; |
zra
2015/01/20 15:23:34
Indentation
Ivan Posva
2015/01/20 16:01:17
Done.
|
- while ((heapTime <= currentTime) || (listTime <= currentTime)) { |
- var timer; |
- // Consume the timers in order by removing from heap or list based on |
- // their wakeup time and update the queue's time. |
- assert((heapTime != listTime) || |
- ((_heap.first != null) && (_firstZeroTimer != null))); |
- if ((heapTime < listTime) || |
- ((heapTime == listTime) && |
- (_heap.first._id < _firstZeroTimer._id))) { |
- timer = _heap.removeFirst(); |
- heapTime = _heap.isEmpty ? (currentTime + 1) : _heap.first._wakeupTime; |
- } else { |
- timer = _firstZeroTimer; |
- assert(timer._milliSeconds == 0); |
- _firstZeroTimer = timer._indexOrNext; |
- if (_firstZeroTimer == null) { |
- _lastZeroTimer = null; |
- listTime = currentTime + 1; |
+ while ((heapTime <= currentTime) || (listTime <= currentTime)) { |
+ var timer; |
+ // Consume the timers in order by removing from heap or list based on |
+ // their wakeup time and update the queue's time. |
+ assert((heapTime != listTime) || |
+ ((_heap.first != null) && (_firstZeroTimer != null))); |
+ if ((heapTime < listTime) || |
+ ((heapTime == listTime) && |
+ (_heap.first._id < _firstZeroTimer._id))) { |
+ timer = _heap.removeFirst(); |
+ heapTime = _heap.isEmpty ? (currentTime + 1) : _heap.first._wakeupTime; |
zra
2015/01/20 15:23:34
Long line
Ivan Posva
2015/01/20 16:01:17
Done.
|
} else { |
- // We want to drain all entries from the list as they should have |
- // been pending for 0 ms. To prevent issues with current time moving |
- // we ensure that the listTime does not go beyond current, unless the |
- // list is empty. |
- listTime = _firstZeroTimer._wakeupTime; |
- if (listTime > currentTime) { |
- listTime = currentTime; |
+ timer = _firstZeroTimer; |
+ assert(timer._milliSeconds == 0); |
+ _firstZeroTimer = timer._indexOrNext; |
+ if (_firstZeroTimer == null) { |
+ _lastZeroTimer = null; |
+ listTime = currentTime + 1; |
+ } else { |
+ // We want to drain all entries from the list as they should have |
+ // been pending for 0 ms. To prevent issues with current time moving |
+ // we ensure that the listTime does not go beyond current, unless |
+ // the list is empty. |
+ listTime = _firstZeroTimer._wakeupTime; |
+ if (listTime > currentTime) { |
+ listTime = currentTime; |
+ } |
} |
} |
- } |
- // Append this timer to the pending timer list. |
- timer._indexOrNext = null; |
- if (head == null) { |
- assert(tail == null); |
- head = timer; |
- tail = timer; |
- } else { |
- tail._indexOrNext = timer; |
- tail = timer; |
+ // Append this timer to the pending timer list. |
+ timer._indexOrNext = null; |
+ if (head == null) { |
+ assert(tail == null); |
+ head = timer; |
+ tail = timer; |
+ } else { |
+ tail._indexOrNext = timer; |
+ tail = timer; |
+ } |
} |
} |
@@ -385,13 +407,16 @@ |
// Creates a receive port and registers an empty handler on that port. Just |
// the triggering of the event loop will ensure that timers are executed. |
- static _ignoreMessage(_) => null; |
+ static _ignoreMessage(_) { |
+ _messagePending = false; |
+ } |
static void _createTimerHandler() { |
assert(_receivePort == null); |
_receivePort = new RawReceivePort(_ignoreMessage); |
_sendPort = _receivePort.sendPort; |
_scheduledWakeupTime = null; |
+ _messagePending = false; |
} |
static void _shutdownTimerHandler() { |
@@ -399,6 +424,7 @@ |
_receivePort = null; |
_sendPort = null; |
_scheduledWakeupTime = null; |
+ _messagePending = false; |
} |
// The Timer factory registered with the dart:async library by the embedder. |