Use Qt::TimerType on Windows when starting timers

Make all Qt::PreciseTimers and timers with intervals < 20ms use
Multimedia timers for maximum accuracy. Qt::CoarseTimers and
Qt::VeryCoarseTimers use normal Windows timers, with
Qt::VeryCoarseTimers having their interval rounded to the nearest
full second.

Note that the Windows timer implementation does not attempt to align
timers and reduce CPU wakeups like the UNIX implementation does. This
might be done in the future, though. However, this change does the
best we can do now, keeping most timers working as-is, while allowing
explicit use of Multimedia timers via Qt::PreciseTimer.

Change-Id: I1898272b101c572a2a9b9454fef27a651eb178f5
Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
Bradley T. Hughes 2012-01-10 10:34:30 +01:00 committed by Qt by Nokia
parent c3ad8c1c06
commit f2edb41c38
2 changed files with 19 additions and 10 deletions

View File

@ -2875,4 +2875,10 @@
\value PreciseTimer Precise timers try to keep millisecond accuracy
\value CoarseTimer Coarse timers try to keep accuracy within 5% of the desired interval
\value VeryCoarseTimer Very coarse timers only keep full second accuracy
On Windows, Qt will use Windows's Multimedia timer facility (if available)
for Qt::PreciseTimer and normal Windows timers for Qt::CoarseTimer and
Qt::VeryCoarseTimer. The interval for Qt::VeryCoarseTimer is rounded to the
nearest full second (e.g. an interval of 23500ms will be rounded to
24000ms, and 20300ms to 20000ms).
*/

View File

@ -530,18 +530,21 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
Q_Q(QEventDispatcherWin32);
int ok = 0;
if (t->interval > 20 || !t->interval || !qtimeSetEvent) {
uint interval = t->interval;
if (interval == 0u) {
// optimization for single-shot-zero-timer
QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
ok = 1;
if (!t->interval) // optimization for single-shot-zero-timer
QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
else
ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
} else {
ok = t->fastTimerId = qtimeSetEvent(t->interval, 1, qt_fast_timer_proc, (DWORD_PTR)t,
} else if ((interval < 20u || t->timerType == Qt::PreciseTimer) && qtimeSetEvent) {
ok = t->fastTimerId = qtimeSetEvent(interval, 1, qt_fast_timer_proc, (DWORD_PTR)t,
TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
if (ok == 0) { // fall back to normal timer if no more multimedia timers available
ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
}
} else if (interval >= 20000u || t->timerType == Qt::VeryCoarseTimer) {
// round the interval, VeryCoarseTimers only have full second accuracy
interval = ((interval + 500)) / 1000 * 1000;
}
if (ok == 0) {
// user normal timers for (Very)CoarseTimers, or if no more multimedia timers available
ok = SetTimer(internalHwnd, t->timerId, interval, 0);
}
if (ok == 0)