summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authoraxis <qt-info@nokia.com>2010-09-23 11:38:04 (GMT)
committeraxis <qt-info@nokia.com>2010-09-23 12:37:30 (GMT)
commit8d8d147f1dd5d2922a4c61c43d378c8784224f13 (patch)
tree5a9570108c9af3b8e3697848eb05b7fb17390282 /src/corelib/kernel
parent5c29d5be5197b265f16c4895776e9be97db845d6 (diff)
downloadQt-8d8d147f1dd5d2922a4c61c43d378c8784224f13.zip
Qt-8d8d147f1dd5d2922a4c61c43d378c8784224f13.tar.gz
Qt-8d8d147f1dd5d2922a4c61c43d378c8784224f13.tar.bz2
Fixed event starvation on Symbian if timers were constantly recreated
If a timer event occurred, and inside its handler a new timer was created that would also immediately occur, the events would execute over and over and starve other events. This happened because the code in Symbian that is supposed to detect when the same event happens more than once does not work if it is always a new timer which executes. The bug was fixed by introducing a state variable which signals whether we are currently inside the handler of a timer event, and then pretending that newly created timers inside this handler have already been executed once, thereby delaying their execution until the next iteration. Because we reset the state variable in processEvents, the behavior will be slightly different if run directly under CActiveScheduler::Start(). There, we have no way of resetting the state on the next iteration, so all timers inside such a handler (even if it recurses into a new CActiveScheduler::Start()) will be delayed by one event iteration. However, this is considered acceptable, since there is no real "iteration count" in the active scheduler; the event will simply be run after the deferred queue is reactivated (which will be immediately if there are no other events). This is the same as what would have happened for a real timer that executed once and then recursed into CActiveScheduler::Start() (it would also be delayed by one iteration). Task: QTBUG-13773 RevBy: mread AutoTest: Passed
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp16
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian_p.h1
2 files changed, 17 insertions, 0 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index 4ac500f..89012d1 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian.cpp
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -724,6 +724,7 @@ QEventDispatcherSymbian::QEventDispatcherSymbian(QObject *parent)
m_interrupt(false),
m_wakeUpDone(0),
m_iterationCount(0),
+ m_insideTimerEvent(false),
m_noSocketEvents(false)
{
#ifdef QT_SYMBIAN_PRIORITY_DROP
@@ -774,6 +775,9 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
{
bool handledAnyEvent = false;
bool oldNoSocketEventsValue = m_noSocketEvents;
+ bool oldInsideTimerEventValue = m_insideTimerEvent;
+
+ m_insideTimerEvent = false;
QT_TRY {
Q_D(QAbstractEventDispatcher);
@@ -864,6 +868,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
}
m_noSocketEvents = oldNoSocketEventsValue;
+ m_insideTimerEvent = oldInsideTimerEventValue;
return handledAnyEvent;
}
@@ -884,10 +889,13 @@ void QEventDispatcherSymbian::timerFired(int timerId)
}
timerInfo->inTimerEvent = true;
+ bool oldInsideTimerEventValue = m_insideTimerEvent;
+ m_insideTimerEvent = true;
QTimerEvent event(timerInfo->timerId);
QCoreApplication::sendEvent(timerInfo->receiver, &event);
+ m_insideTimerEvent = oldInsideTimerEventValue;
timerInfo->inTimerEvent = false;
return;
@@ -1054,6 +1062,14 @@ void QEventDispatcherSymbian::registerTimer ( int timerId, int interval, QObject
m_timerList.insert(timerId, timer);
timer->timerAO->Start();
+
+ if (m_insideTimerEvent)
+ // If we are inside a timer event, we need to prevent event starvation
+ // by preventing newly created timers from running in the same event processing
+ // iteration. Do this by calling the okToRun() function to "fake" that we have
+ // already run once. This will cause the next run to be added to the deferred
+ // queue instead.
+ timer->timerAO->okToRun();
}
bool QEventDispatcherSymbian::unregisterTimer ( int timerId )
diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h
index 53afebe..8e20d56 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian_p.h
+++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h
@@ -274,6 +274,7 @@ private:
QAtomicInt m_wakeUpDone;
unsigned char m_iterationCount;
+ bool m_insideTimerEvent;
bool m_noSocketEvents;
QList<QSocketActiveObject *> m_deferredSocketEvents;