diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian.cpp | 125 | ||||
| -rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian_p.h | 34 | ||||
| -rw-r--r-- | src/gui/styles/qs60style_s60.cpp | 4 | ||||
| -rw-r--r-- | src/s60installs/bwins/QtCoreu.def | 5 | ||||
| -rw-r--r-- | src/s60installs/eabi/QtCoreu.def | 5 |
5 files changed, 161 insertions, 12 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index fca2feb..ef331f6 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE #define WAKE_UP_PRIORITY CActive::EPriorityStandard #define TIMER_PRIORITY CActive::EPriorityHigh +#define COMPLETE_DEFERRED_ACTIVE_OBJECTS_PRIORITY CActive::EPriorityIdle class Incrementer { int &variable; @@ -140,17 +141,49 @@ private: }; /* - * This class can be used as a base class for Qt active objects. + * This class is designed to aid in implementing event handling in a more round robin fashion, + * when Qt active objects are used outside of QtRRActiveScheduler. + * We cannot change active objects that we do not own, but active objects that Qt owns may use + * this as a base class with convenience functions. + * + * Here is how it works: On every RunL, the deriving class should call maybeQueueForLater(). + * This will return whether the active object has been queued, or whether it should run immediately. + * Queued objects will run again after other events have been processed. + * + * The QCompleteDeferredAOs class is a special object that runs after all others, which will + * reactivate the objects that were previously not run. * Socket active objects can use it to defer their activity. */ QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher) : CActive(priority), - m_dispatcher(dispatcher) + m_dispatcher(dispatcher), + m_hasAlreadyRun(false), + m_hasRunAgain(false), + m_iterationCount(1) { } QActiveObject::~QActiveObject() { + if (m_hasRunAgain) + m_dispatcher->removeDeferredActiveObject(this); +} + +bool QActiveObject::maybeQueueForLater() +{ + Q_ASSERT(!m_hasRunAgain); + + if (!m_hasAlreadyRun || m_dispatcher->iterationCount() != m_iterationCount) { + // First occurrence of this event in this iteration. + m_hasAlreadyRun = true; + m_iterationCount = m_dispatcher->iterationCount(); + return false; + } else { + // The event has already occurred. + m_dispatcher->addDeferredActiveObject(this); + m_hasRunAgain = true; + return true; + } } bool QActiveObject::maybeDeferSocketEvent() @@ -170,6 +203,9 @@ void QActiveObject::reactivateAndComplete() SetActive(); TRequestStatus *status = &iStatus; QEventDispatcherSymbian::RequestComplete(status, error); + + m_hasRunAgain = false; + m_hasAlreadyRun = false; } QWakeUpActiveObject::QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher) @@ -212,8 +248,8 @@ void QWakeUpActiveObject::RunL() } QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo) - : CActive(TIMER_PRIORITY), - m_dispatcher(dispatcher), m_timerInfo(timerInfo), m_expectedTimeSinceLastEvent(0) + : QActiveObject(TIMER_PRIORITY, dispatcher), + m_timerInfo(timerInfo), m_expectedTimeSinceLastEvent(0) { // start the timeout timer to ensure initialisation m_timeoutTimer.start(); @@ -290,6 +326,9 @@ void QTimerActiveObject::Run() return; } + if (maybeQueueForLater()) + return; + if (m_timerInfo->interval > 0) { // Start a new timer immediately so that we don't lose time. m_timerInfo->msLeft = m_timerInfo->interval; @@ -341,6 +380,44 @@ SymbianTimerInfo::~SymbianTimerInfo() delete timerAO; } +QCompleteDeferredAOs::QCompleteDeferredAOs(QEventDispatcherSymbian *dispatcher) + : CActive(COMPLETE_DEFERRED_ACTIVE_OBJECTS_PRIORITY), + m_dispatcher(dispatcher) +{ + CActiveScheduler::Add(this); + iStatus = KRequestPending; + SetActive(); +} + +QCompleteDeferredAOs::~QCompleteDeferredAOs() +{ + Cancel(); +} + +void QCompleteDeferredAOs::complete() +{ + if (iStatus.Int() == KRequestPending) { + TRequestStatus *status = &iStatus; + QEventDispatcherSymbian::RequestComplete(status, KErrNone); + } +} + +void QCompleteDeferredAOs::DoCancel() +{ + if (iStatus.Int() == KRequestPending) { + TRequestStatus *status = &iStatus; + QEventDispatcherSymbian::RequestComplete(status, KErrNone); + } +} + +void QCompleteDeferredAOs::RunL() +{ + iStatus = KRequestPending; + SetActive(); + + QT_TRYCATCH_LEAVING(m_dispatcher->reactivateDeferredActiveObjects()); +} + QSelectThread::QSelectThread() : m_quit(false) { @@ -879,6 +956,7 @@ QEventDispatcherSymbian::QEventDispatcherSymbian(QObject *parent) m_selectThread(0), m_activeScheduler(0), m_wakeUpAO(0), + m_completeDeferredAOs(0), m_interrupt(false), m_wakeUpDone(0), m_iterationCount(0), @@ -903,6 +981,7 @@ void QEventDispatcherSymbian::startingUp() CActiveScheduler::Install(m_activeScheduler); } m_wakeUpAO = q_check_ptr(new QWakeUpActiveObject(this)); + m_completeDeferredAOs = q_check_ptr(new QCompleteDeferredAOs(this)); // We already might have posted events, wakeup once to process them wakeUp(); } @@ -921,6 +1000,7 @@ void QEventDispatcherSymbian::closingDown() delete m_selectThread; m_selectThread = 0; + delete m_completeDeferredAOs; delete m_wakeUpAO; if (m_activeScheduler) { delete m_activeScheduler; @@ -1153,6 +1233,35 @@ inline void QEventDispatcherSymbian::addDeferredSocketActiveObject(QActiveObject m_deferredSocketEvents.append(object); } +inline void QEventDispatcherSymbian::addDeferredActiveObject(QActiveObject *object) +{ + queueDeferredActiveObjectsCompletion(); + m_deferredActiveObjects.append(object); +} + +inline void QEventDispatcherSymbian::removeDeferredActiveObject(QActiveObject *object) +{ + m_deferredActiveObjects.removeAll(object); +} + +void QEventDispatcherSymbian::queueDeferredActiveObjectsCompletion() +{ + m_completeDeferredAOs->complete(); +} + +void QEventDispatcherSymbian::reactivateDeferredActiveObjects() +{ + while (!m_deferredActiveObjects.isEmpty()) { + QActiveObject *object = m_deferredActiveObjects.takeFirst(); + object->reactivateAndComplete(); + } + + // We do this because we want to return from processEvents. This is because + // each invocation of processEvents should only run each active object once. + // The active scheduler should run them continously, however. + m_interrupt = true; +} + bool QEventDispatcherSymbian::sendDeferredSocketEvents() { bool sentAnyEvents = false; @@ -1228,6 +1337,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 maybeQueueForLater() 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->maybeQueueForLater(); } bool QEventDispatcherSymbian::unregisterTimer ( int timerId ) diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index 1b81599..01f5ab1 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -84,10 +84,15 @@ public: ~QActiveObject(); bool maybeDeferSocketEvent(); - + bool maybeQueueForLater(); void reactivateAndComplete(); protected: QEventDispatcherSymbian *m_dispatcher; + +private: + bool m_hasAlreadyRun : 1; + bool m_hasRunAgain : 1; + int m_iterationCount; }; class QWakeUpActiveObject : public CActive @@ -124,7 +129,7 @@ struct SymbianTimerInfo : public QSharedData typedef QExplicitlySharedDataPointer<SymbianTimerInfo> SymbianTimerInfoPtr; // This is a bit of a proxy class. See comments in SetActive and Start for details. -class QTimerActiveObject : public CActive +class QTimerActiveObject : public QActiveObject { public: QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo); @@ -141,13 +146,28 @@ private: void StartTimer(); private: - QEventDispatcherSymbian *m_dispatcher; SymbianTimerInfo *m_timerInfo; QElapsedTimer m_timeoutTimer; int m_expectedTimeSinceLastEvent; RTimer m_rTimer; }; +class QCompleteDeferredAOs : public CActive +{ +public: + QCompleteDeferredAOs(QEventDispatcherSymbian *dispatcher); + ~QCompleteDeferredAOs(); + + void complete(); + +protected: + void DoCancel(); + void RunL(); + +private: + QEventDispatcherSymbian *m_dispatcher; +}; + class QSocketActiveObject : public QActiveObject { public: @@ -231,6 +251,11 @@ public: void wakeUpWasCalled(); void reactivateSocketNotifier(QSocketNotifier *notifier); + void addDeferredActiveObject(QActiveObject *object); + void removeDeferredActiveObject(QActiveObject *object); + void queueDeferredActiveObjectsCompletion(); + // Can be overridden to activate local active objects too, but do call baseclass! + virtual void reactivateDeferredActiveObjects(); inline int iterationCount() const { return m_iterationCount; } void addDeferredSocketActiveObject(QActiveObject *object); @@ -253,6 +278,7 @@ private: QHash<QSocketNotifier *, QSocketActiveObject *> m_notifiers; QWakeUpActiveObject *m_wakeUpAO; + QCompleteDeferredAOs *m_completeDeferredAOs; volatile bool m_interrupt; QAtomicInt m_wakeUpDone; @@ -263,6 +289,8 @@ private: //deferred until socket events are enabled QList<QActiveObject *> m_deferredSocketEvents; + QList<QActiveObject *> m_deferredActiveObjects; + int m_delay; int m_avgEventTime; QElapsedTimer m_lastIdleRequestTimer; diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index eb59115..08884d8 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -1347,7 +1347,9 @@ QS60StylePrivate::QS60StylePrivate() void QS60StylePrivate::removeAnimations() { //currently only one animation in the list. - m_animations()->removeFirst(); + if (!m_animations()->isEmpty()) { + delete m_animations()->takeFirst(); + } } QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list, diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index 3437502..9181dd7 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4484,8 +4484,8 @@ EXPORTS ?selectThread@QEventDispatcherSymbian@@AAEAAVQSelectThread@@XZ @ 4483 NONAME ; class QSelectThread & QEventDispatcherSymbian::selectThread(void) ?qt_symbian_SetupThreadHeap@@YAHHAAUSStdEpocThreadCreateInfo@@@Z @ 4484 NONAME ; int qt_symbian_SetupThreadHeap(int, struct SStdEpocThreadCreateInfo &) ?objectNameChanged@QAbstractDeclarativeData@@2P6AXPAV1@PAVQObject@@@ZA @ 4485 NONAME ; void (*QAbstractDeclarativeData::objectNameChanged)(class QAbstractDeclarativeData *, class QObject *) - ?queueDeferredActiveObjectsCompletion@QEventDispatcherSymbian@@QAEXXZ @ 4486 NONAME ABSENT ; void QEventDispatcherSymbian::queueDeferredActiveObjectsCompletion(void) - ?reactivateDeferredActiveObjects@QEventDispatcherSymbian@@UAEXXZ @ 4487 NONAME ABSENT ; void QEventDispatcherSymbian::reactivateDeferredActiveObjects(void) + ?queueDeferredActiveObjectsCompletion@QEventDispatcherSymbian@@QAEXXZ @ 4486 NONAME ; void QEventDispatcherSymbian::queueDeferredActiveObjectsCompletion(void) + ?reactivateDeferredActiveObjects@QEventDispatcherSymbian@@UAEXXZ @ 4487 NONAME ; void QEventDispatcherSymbian::reactivateDeferredActiveObjects(void) ?symbianCommandLine@QCoreApplicationPrivate@@SAPAVCApaCommandLine@@XZ @ 4488 NONAME ; class CApaCommandLine * QCoreApplicationPrivate::symbianCommandLine(void) ?revision@QMetaProperty@@QBEHXZ @ 4489 NONAME ; int QMetaProperty::revision(void) const ?revision@QMetaMethod@@QBEHXZ @ 4490 NONAME ; int QMetaMethod::revision(void) const @@ -4884,4 +4884,5 @@ EXPORTS ?event@QFutureWatcherBase@@UAE_NPAVQEvent@@@Z @ 4883 NONAME ; bool QFutureWatcherBase::event(class QEvent *) ?updateDir@QFactoryLoader@@QAEXABVQString@@AAVQSettings@@@Z @ 4884 NONAME ; void QFactoryLoader::updateDir(class QString const &, class QSettings &) ?disconnectNotify@QFutureWatcherBase@@MAEXPBD@Z @ 4885 NONAME ; void QFutureWatcherBase::disconnectNotify(char const *) + ?maybeQueueForLater@QActiveObject@@QAE_NXZ @ 4886 NONAME ; bool QActiveObject::maybeQueueForLater(void) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index 1fabdb2..5436390 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -1294,7 +1294,7 @@ EXPORTS _ZN23QEventDispatcherSymbian24reactivateSocketNotifierEP15QSocketNotifier @ 1293 NONAME _ZN23QEventDispatcherSymbian24sendDeferredSocketEventsEv @ 1294 NONAME _ZN23QEventDispatcherSymbian24unregisterSocketNotifierEP15QSocketNotifier @ 1295 NONAME - _ZN23QEventDispatcherSymbian31reactivateDeferredActiveObjectsEv @ 1296 NONAME ABSENT + _ZN23QEventDispatcherSymbian31reactivateDeferredActiveObjectsEv @ 1296 NONAME _ZN23QEventDispatcherSymbian5flushEv @ 1297 NONAME _ZN23QEventDispatcherSymbian6wakeUpEv @ 1298 NONAME _ZN23QEventDispatcherSymbian9interruptEv @ 1299 NONAME @@ -3713,7 +3713,7 @@ EXPORTS _ZrsR11QDataStreamR12QEasingCurve @ 3712 NONAME _Z26qt_symbian_SetupThreadHeapiR24SStdEpocThreadCreateInfo @ 3713 NONAME _ZN24QAbstractDeclarativeData17objectNameChangedE @ 3714 NONAME DATA 4 - _ZN23QEventDispatcherSymbian36queueDeferredActiveObjectsCompletionEv @ 3715 NONAME ABSENT + _ZN23QEventDispatcherSymbian36queueDeferredActiveObjectsCompletionEv @ 3715 NONAME _ZN23QCoreApplicationPrivate18symbianCommandLineEv @ 3716 NONAME _ZNK11QMetaMethod8revisionEv @ 3717 NONAME _ZNK13QMetaProperty8revisionEv @ 3718 NONAME @@ -4164,4 +4164,5 @@ EXPORTS zlibCompileFlags @ 4163 NONAME _ZN14QFactoryLoader9updateDirERK7QStringR9QSettings @ 4164 NONAME _ZN23QCoreApplicationPrivate26rebuildInstallLibraryPathsEv @ 4165 NONAME + _ZN13QActiveObject18maybeQueueForLaterEv @ 4166 NONAME |
