| Index: runtime/lib/timer_impl.dart
|
| ===================================================================
|
| --- runtime/lib/timer_impl.dart (revision 44189)
|
| +++ 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,36 @@
|
| 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 handler to wake this isolate at a specific time.
|
| + static void _scheduleWakeup(int wakeupTime) {
|
| + if (_sendPort == null) {
|
| + _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;
|
| + }
|
| +
|
| +
|
| + // Create a receive port and register a message handler for the timer
|
| + // events.
|
| static void _createTimerHandler() {
|
| assert(_receivePort == null);
|
| assert(_sendPort == null);
|
| @@ -415,6 +443,7 @@
|
| _scheduledWakeupTime = null;
|
| }
|
|
|
| +
|
| static void _shutdownTimerHandler() {
|
| _receivePort.close();
|
| _receivePort = null;
|
| @@ -422,6 +451,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 +463,7 @@
|
| }
|
| }
|
|
|
| +
|
| _setupHooks() {
|
| VMLibraryHooks.timerFactory = _Timer._factory;
|
| }
|
|
|