summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qeventdispatcher_symbian.cpp
diff options
context:
space:
mode:
authormread <qt-info@nokia.com>2011-04-20 09:02:16 (GMT)
committermread <qt-info@nokia.com>2011-04-20 09:02:16 (GMT)
commitbe4d73861441bd39d946d71b93f7f6f0ab445b50 (patch)
treeccb8a6884747261bb6ddccb28e3b031aed613bbe /src/corelib/kernel/qeventdispatcher_symbian.cpp
parent990cb4de8ba27ad157ffa8854b49f05f41a2ac28 (diff)
downloadQt-be4d73861441bd39d946d71b93f7f6f0ab445b50.zip
Qt-be4d73861441bd39d946d71b93f7f6f0ab445b50.tar.gz
Qt-be4d73861441bd39d946d71b93f7f6f0ab445b50.tar.bz2
Drift correction and better accuracy for repeating timers in Symbian
Timers on Symbian were always firing at least 2ms late. This was partly due to a paranoid extra delay in Qt and the kernel being very cautious. For one shot timers this is not so bad although a bit too much. But for repeating timers, this can cause significant reductions in firing rate particularly for short period timers. The timer active object now corrects timer lateness by up to 4ms per event. This is enough to compensate for the kernel lateness without the possibility of wild corrections. Task-number: QTBUG-18549 Reviewed-by: iain
Diffstat (limited to 'src/corelib/kernel/qeventdispatcher_symbian.cpp')
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp27
1 files changed, 22 insertions, 5 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index 47dd558..84825af 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian.cpp
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -210,8 +210,10 @@ void QWakeUpActiveObject::RunL()
QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo)
: QActiveObject((timerInfo->interval) ? TIMER_PRIORITY : NULLTIMER_PRIORITY , dispatcher),
- m_timerInfo(timerInfo)
+ m_timerInfo(timerInfo), m_expectedTimeSinceLastEvent(0)
{
+ // start the timeout timer to ensure initialisation
+ m_timeoutTimer.start();
}
QTimerActiveObject::~QTimerActiveObject()
@@ -255,10 +257,23 @@ void QTimerActiveObject::StartTimer()
m_rTimer.After(iStatus, MAX_SYMBIAN_TIMEOUT_MS * 1000);
m_timerInfo->msLeft -= MAX_SYMBIAN_TIMEOUT_MS;
} else {
- //HighRes gives the 1ms accuracy expected by Qt, the +1 is to ensure that
- //"Timers will never time out earlier than the specified timeout value"
- //condition is always met.
- m_rTimer.HighRes(iStatus, (m_timerInfo->msLeft + 1) * 1000);
+ // this algorithm implements drift correction for repeating timers
+ // calculate how late we are for this event
+ int timeSinceLastEvent = m_timeoutTimer.restart();
+ int overshoot = timeSinceLastEvent - m_expectedTimeSinceLastEvent;
+ if (overshoot > m_timerInfo->msLeft) {
+ // we skipped a whole timeout, restart from here
+ overshoot = 0;
+ }
+ // calculate when the next event should happen
+ int waitTime = m_timerInfo->msLeft - overshoot;
+ m_expectedTimeSinceLastEvent = waitTime;
+ // limit the actual ms wait time to avoid wild corrections
+ // this will cause the real event time to slowly drift back to the expected event time
+ // measurements show that Symbian timers always fire 1 or 2 ms late
+ const int limit = 4;
+ waitTime = qMax(m_timerInfo->msLeft - limit, waitTime);
+ m_rTimer.HighRes(iStatus, waitTime * 1000);
m_timerInfo->msLeft = 0;
}
SetActive();
@@ -305,6 +320,8 @@ void QTimerActiveObject::Start()
if (!m_rTimer.Handle()) {
qt_symbian_throwIfError(m_rTimer.CreateLocal());
}
+ m_timeoutTimer.start();
+ m_expectedTimeSinceLastEvent = 0;
StartTimer();
} else {
iStatus = KRequestPending;