Chromium Code Reviews| Index: runtime/lib/timer_impl.dart |
| =================================================================== |
| --- runtime/lib/timer_impl.dart (revision 44177) |
| +++ runtime/lib/timer_impl.dart (working copy) |
| @@ -115,7 +115,7 @@ |
| class _Timer implements Timer { |
| // Cancels the timer in the event handler. |
| - static const int _NO_TIMER = -1; |
| + static const _NO_TIMER = -1; |
| // We distinguish what kind of message arrived based on the value being sent. |
| static const _ZERO_EVENT = 1; |
| @@ -129,7 +129,7 @@ |
| // We use an id to be able to sort timers with the same expiration time. |
| // ids are recycled after ID_MASK enqueues or when the timer queue is empty. |
| - static int _ID_MASK = 0x1fffffff; |
| + static const _ID_MASK = 0x1fffffff; |
| static int _idCount = 0; |
| static RawReceivePort _receivePort; |
| @@ -140,11 +140,12 @@ |
| Function _callback; // Closure to call when timer fires. null if canceled. |
| int _wakeupTime; // Expiration time. |
| - int _milliSeconds; // Duration specified at creation. |
| - bool _repeating; // Indicates periodic timers. |
| + final int _milliSeconds; // Duration specified at creation. |
| + final bool _repeating; // Indicates periodic timers. |
| var _indexOrNext; // Index if part of the TimerHeap, link otherwise. |
| int _id; // Incrementing id to enable sorting of timers with same expiry. |
| + |
| // Get the next available id. We accept collisions and reordering when the |
| // _idCount overflows and the timers expire at the same millisecond. |
| static int _nextId() { |
| @@ -153,11 +154,13 @@ |
| return result; |
| } |
| + |
| _Timer._internal(this._callback, |
| this._wakeupTime, |
| this._milliSeconds, |
| this._repeating) : _id = _nextId(); |
| + |
| static Timer _createTimer(void callback(Timer timer), |
| int milliSeconds, |
| bool repeating) { |
| @@ -182,24 +185,30 @@ |
| return timer; |
| } |
| + |
| factory _Timer(int milliSeconds, void callback(Timer timer)) { |
| return _createTimer(callback, milliSeconds, false); |
| } |
| + |
| factory _Timer.periodic(int milliSeconds, void callback(Timer timer)) { |
| return _createTimer(callback, milliSeconds, true); |
| } |
| + |
| bool get _isInHeap => _indexOrNext is int; |
| + |
| int _compareTo(_Timer other) { |
| int c = _wakeupTime - other._wakeupTime; |
| if (c != 0) return c; |
| return _id - other._id; |
| } |
| + |
| bool get isActive => _callback != null; |
| + |
| // Cancels a set timer. The timer is removed from the timer heap if it is a |
| // non-zero timer. Zero timers are kept in the list as they need to consume |
| // the corresponding pending message. |
| @@ -215,6 +224,7 @@ |
| } |
| } |
| + |
| void _advanceWakeupTime() { |
| // Recalculate the next wakeup time. For repeating timers with a 0 timeout |
| // the next wakeup time is now. |
| @@ -226,6 +236,7 @@ |
| } |
| } |
| + |
| // Adds a timer to the heap or timer list. Timers with the same wakeup time |
| // are enqueued in order and notified in FIFO order. |
| void _enqueue() { |
| @@ -292,13 +303,13 @@ |
| // No pending timers: Close the receive port and let the event handler |
| // know. |
| if (_sendPort != null) { |
| - VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER); |
| + _cancelWakeup(); |
| _shutdownTimerHandler(); |
| } |
| return; |
| } else if (_heap.isEmpty) { |
| // Only zero timers are left. Cancel any scheduled wakeups. |
| - VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER); |
| + _cancelWakeup(); |
| return; |
| } |
| @@ -307,16 +318,11 @@ |
| var wakeupTime = _heap.first._wakeupTime; |
| if ((_scheduledWakeupTime == null) || |
| (wakeupTime != _scheduledWakeupTime)) { |
| - if (_sendPort == null) { |
| - // Create a receive port and register a message handler for the timer |
| - // events. |
| - _createTimerHandler(); |
| - } |
| - VMLibraryHooks.eventHandlerSendData(null, _sendPort, wakeupTime); |
| - _scheduledWakeupTime = wakeupTime; |
| + _scheduleWakeup(wakeupTime); |
| } |
| } |
| + |
| static List _queueFromTimeoutEvent() { |
| var pendingTimers = new List(); |
| if (_firstZeroTimer != null) { |
| @@ -344,6 +350,7 @@ |
| return pendingTimers; |
| } |
| + |
| static void _runTimers(List pendingTimers) { |
| // If there are no pending timers currently reset the id space before we |
| // have a chance to enqueue new timers. |
| @@ -387,14 +394,10 @@ |
| } |
| } finally { |
| _handlingCallbacks = false; |
| - // Notify the event handler or shutdown the port if no more pending |
| - // timers are present. |
| - _notifyEventHandler(); |
| } |
| } |
| - // 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 void _handleMessage(msg) { |
| var pendingTimers; |
| if (msg == _ZERO_EVENT) { |
| @@ -402,11 +405,37 @@ |
| assert(pendingTimers.length > 0); |
| } else { |
| assert(msg == _TIMEOUT_EVENT); |
| + _scheduledWakeupTime = null; // Consumed the last scheduled wakeup now. |
| pendingTimers = _queueFromTimeoutEvent(); |
| } |
| _runTimers(pendingTimers); |
| + // Notify the event handler or shutdown the port if no more pending |
| + // timers are present. |
| + _notifyEventHandler(); |
| } |
| + |
| + // Tell the event handle to wake this isolate at a specific time. |
|
koda
2015/03/03 18:58:51
handle -> handler
Ivan Posva
2015/03/03 19:14:18
Acknowledged.
|
| + static void _scheduleWakeup(int wakeupTime) { |
| + if (_sendPort == null) { |
| + // Create a receive port and register a message handler for the timer |
|
koda
2015/03/03 18:58:51
Move this comment to the actual method.
Ivan Posva
2015/03/03 19:14:18
Done.
|
| + // events. |
| + _createTimerHandler(); |
| + } |
| + VMLibraryHooks.eventHandlerSendData(null, _sendPort, wakeupTime); |
| + _scheduledWakeupTime = wakeupTime; |
| + } |
| + |
| + |
| + // Cancel pending wakeups in the event handler. |
| + static void _cancelWakeup() { |
| + assert(_sendPort != null); |
| + VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER); |
| + _scheduledWakeupTime = null; |
| + |
|
koda
2015/03/03 18:58:51
Remove blank line.
Ivan Posva
2015/03/03 19:14:18
Done.
|
| + } |
| + |
| + |
| static void _createTimerHandler() { |
| assert(_receivePort == null); |
| assert(_sendPort == null); |
| @@ -415,6 +444,7 @@ |
| _scheduledWakeupTime = null; |
| } |
| + |
| static void _shutdownTimerHandler() { |
| _receivePort.close(); |
| _receivePort = null; |
| @@ -422,6 +452,7 @@ |
| _scheduledWakeupTime = null; |
| } |
| + |
| // The Timer factory registered with the dart:async library by the embedder. |
| static Timer _factory(int milliSeconds, |
| void callback(Timer timer), |
| @@ -433,6 +464,7 @@ |
| } |
| } |
| + |
| _setupHooks() { |
| VMLibraryHooks.timerFactory = _Timer._factory; |
| } |