diff options
author | Shane Kearns <shane.kearns@sosco.com> | 2009-09-16 13:48:59 (GMT) |
---|---|---|
committer | Shane Kearns <shane.kearns@sosco.com> | 2009-09-16 13:48:59 (GMT) |
commit | 504dd08854a8f6519a0529014df2233938b82728 (patch) | |
tree | c96594b5b69bcd10d61b97fd9838505208eb7610 /src/corelib | |
parent | 314e5680c8276d539b596927874036a873966d8f (diff) | |
download | Qt-504dd08854a8f6519a0529014df2233938b82728.zip Qt-504dd08854a8f6519a0529014df2233938b82728.tar.gz Qt-504dd08854a8f6519a0529014df2233938b82728.tar.bz2 |
Fix QTimer overflow with interval > 35 minutes on symbian
For long intervals, restart the system timer every 2000 seconds
New autotest to verify long timers don't crash or complete immediately
Task-number: QT-651
Reviewed-by: axis
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian.cpp | 33 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian_p.h | 2 |
2 files changed, 30 insertions, 5 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index b1c8734..11a0da6 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -231,15 +231,39 @@ void QTimerActiveObject::RunL() } } +#define MAX_SYMBIAN_TIMEOUT_MS 2000000 +void QTimerActiveObject::StartTimer() +{ + if (m_timerInfo->msLeft > MAX_SYMBIAN_TIMEOUT_MS) { + //There is loss of accuracy anyway due to needing to restart the timer every 33 minutes, + //so the 1/64s res of After() is acceptable for these very long timers. + 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); + m_timerInfo->msLeft = 0; + } + SetActive(); +} + void QTimerActiveObject::Run() { + //restart timer immediately, if the timeout has been split because it overflows max for platform. + if (m_timerInfo->msLeft > 0) { + StartTimer(); + return; + } + if (!okToRun()) return; if (m_timerInfo->interval > 0) { // Start a new timer immediately so that we don't lose time. - SetActive(); - m_rTimer.After(iStatus, m_timerInfo->interval*1000); + m_timerInfo->msLeft = m_timerInfo->interval; + StartTimer(); m_timerInfo->dispatcher->timerFired(m_timerInfo->timerId); } else { @@ -261,11 +285,10 @@ void QTimerActiveObject::Run() void QTimerActiveObject::Start() { CActiveScheduler::Add(this); + m_timerInfo->msLeft = m_timerInfo->interval; if (m_timerInfo->interval > 0) { m_rTimer.CreateLocal(); - iStatus = KRequestPending; - SetActive(); - m_rTimer.After(iStatus, m_timerInfo->interval*1000); + StartTimer(); } else { iStatus = KRequestPending; SetActive(); diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index 53f92a9..fd0350d 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -117,6 +117,7 @@ struct SymbianTimerInfo : public QSharedData int timerId; int interval; + int msLeft; bool inTimerEvent; QObject *receiver; QTimerActiveObject *timerAO; @@ -140,6 +141,7 @@ protected: private: void Run(); + void StartTimer(); private: SymbianTimerInfo *m_timerInfo; |