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

Unified 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, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/lib/async/timer_regress22626_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
}
« no previous file with comments | « no previous file | tests/lib/async/timer_regress22626_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698