Unix (non-Glib) event dispatcher: round sleep to millisecond boundary.
authorThiago Macieira <thiago.macieira@nokia.com>
Wed, 30 Jun 2010 13:18:24 +0000 (15:18 +0200)
committerQt by Nokia <qt-info@nokia.com>
Thu, 27 Oct 2011 09:12:38 +0000 (11:12 +0200)
If we have two timers running in an application with the same timeout
and started almost at the same time by the code, they would trigger two
sleeps, the second of which very short (under a millisecond).

This causes us to match the Glib and Windows event loops, which round
all timers to millisecond anyway.

Change-Id: I7eb531e02dadf75925c01192b0f33ef3641ae1ea
Reviewed-by: Olivier Goffart <ogoffart@kde.org>
src/corelib/kernel/qeventdispatcher_unix.cpp

index f2f9dd6..3c7a48a 100644 (file)
@@ -441,6 +441,20 @@ void QTimerInfoList::timerRepair(const timeval &diff)
     }
 }
 
+static timeval roundToMillisecond(timeval val)
+{
+    // always round up
+    // worst case scenario is that the first trigger of a 1-ms timer is 0.999 ms late
+
+    int us = val.tv_usec % 1000;
+    val.tv_usec += 1000 - us;
+    if (val.tv_usec > 1000000) {
+        val.tv_usec -= 1000000;
+        ++val.tv_sec;
+    }
+    return val;
+}
+
 /*
   Returns the time to wait for the next timer, or null if no timers
   are waiting.
@@ -464,7 +478,7 @@ bool QTimerInfoList::timerWait(timeval &tm)
 
     if (currentTime < t->timeout) {
         // time to wait
-        tm = t->timeout - currentTime;
+        tm = roundToMillisecond(t->timeout - currentTime);
     } else {
         // no time to wait
         tm.tv_sec  = 0;