summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp143
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian_p.h44
-rw-r--r--tests/auto/qtimer/tst_qtimer.cpp3
3 files changed, 129 insertions, 61 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index 1581d9b21e..e1e3e0e536 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian.cpp
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -22,7 +22,7 @@ QT_BEGIN_NAMESPACE
#define WAKE_UP_PRIORITY CActive::EPriorityStandard
#define TIMER_PRIORITY CActive::EPriorityLow
-#define COMPLETE_ZERO_TIMERS_PRIORITY CActive::EPriorityIdle
+#define COMPLETE_DEFERRED_ACTIVE_OBJECTS_PRIORITY CActive::EPriorityIdle
static inline int qt_pipe_write(int socket, const char *data, qint64 len)
{
@@ -82,6 +82,57 @@ private:
QMutex *m_mutex;
};
+/*
+ * This class is designed to aid in implementing event handling in a more round robin fashion. We
+ * cannot change active objects that we do not own, but the active objects that Qt owns will use
+ * this as a base class with convenience functions.
+ *
+ * Here is how it works: On every RunL, the deriving class should call okToRun(). This will allow
+ * exactly one run of the active object, and mark it as such. If it is called again, it will return
+ * false, and add the object to a queue so it can be run later.
+ *
+ * The QCompleteDeferredAOs class is a special object that runs after all others, which will
+ * reactivate the objects that were previously not run.
+ */
+inline QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher)
+ : CActive(priority),
+ m_dispatcher(dispatcher),
+ m_hasAlreadyRun(false),
+ m_hasRunAgain(false)
+{
+}
+
+QActiveObject::~QActiveObject()
+{
+ if (m_hasRunAgain)
+ m_dispatcher->removeDeferredActiveObject(this);
+}
+
+bool QActiveObject::okToRun()
+{
+ Q_ASSERT(!m_hasRunAgain);
+
+ if (m_hasAlreadyRun) {
+ m_dispatcher->addDeferredActiveObject(this);
+ m_hasRunAgain = true;
+ return false;
+ } else {
+ m_hasAlreadyRun = true;
+ return true;
+ }
+}
+
+void QActiveObject::reactivateAndComplete()
+{
+ iStatus = KRequestPending;
+ SetActive();
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+
+ m_hasRunAgain = false;
+ m_hasAlreadyRun = false;
+}
+
QWakeUpActiveObject::QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher)
: CActive(WAKE_UP_PRIORITY),
m_dispatcher(dispatcher)
@@ -111,8 +162,8 @@ void QWakeUpActiveObject::RunL()
m_dispatcher->wakeUpWasCalled();
}
-QTimerActiveObject::QTimerActiveObject(SymbianTimerInfo *timerInfo)
- : CActive(TIMER_PRIORITY),
+QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo)
+ : QActiveObject(TIMER_PRIORITY, dispatcher),
m_timerInfo(timerInfo)
{
}
@@ -137,6 +188,9 @@ void QTimerActiveObject::DoCancel()
void QTimerActiveObject::RunL()
{
+ if (!okToRun())
+ return;
+
if (m_timerInfo->interval > 0) {
// Start a new timer immediately so that we don't lose time.
iStatus = KRequestPending;
@@ -155,7 +209,8 @@ void QTimerActiveObject::RunL()
iStatus = KRequestPending;
SetActive();
- // We complete it when the QCompleteZeroTimersActiveObject is run.
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
}
}
@@ -180,33 +235,29 @@ SymbianTimerInfo::~SymbianTimerInfo()
delete timerAO;
}
-QCompleteZeroTimersActiveObject::QCompleteZeroTimersActiveObject(QEventDispatcherSymbian *dispatcher)
- : CActive(COMPLETE_ZERO_TIMERS_PRIORITY),
+QCompleteDeferredAOs::QCompleteDeferredAOs(QEventDispatcherSymbian *dispatcher)
+ : CActive(COMPLETE_DEFERRED_ACTIVE_OBJECTS_PRIORITY),
m_dispatcher(dispatcher)
{
CActiveScheduler::Add(this);
iStatus = KRequestPending;
SetActive();
- TRequestStatus *status = &iStatus;
- QEventDispatcherSymbian::RequestComplete(status, KErrNone);
}
-QCompleteZeroTimersActiveObject::~QCompleteZeroTimersActiveObject()
+QCompleteDeferredAOs::~QCompleteDeferredAOs()
{
Cancel();
}
-bool QCompleteZeroTimersActiveObject::ref()
+void QCompleteDeferredAOs::complete()
{
- return (++m_refCount != 0);
-}
-
-bool QCompleteZeroTimersActiveObject::deref()
-{
- return (--m_refCount != 0);
+ if (iStatus.Int() & KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
}
-void QCompleteZeroTimersActiveObject::DoCancel()
+void QCompleteDeferredAOs::DoCancel()
{
if (iStatus.Int() & KRequestPending) {
TRequestStatus *status = &iStatus;
@@ -214,14 +265,12 @@ void QCompleteZeroTimersActiveObject::DoCancel()
}
}
-void QCompleteZeroTimersActiveObject::RunL()
+void QCompleteDeferredAOs::RunL()
{
- m_dispatcher->completeZeroTimers();
-
iStatus = KRequestPending;
SetActive();
- TRequestStatus *status = &iStatus;
- QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+
+ m_dispatcher->reactivateDeferredActiveObjects();
}
QSelectThread::QSelectThread()
@@ -432,8 +481,7 @@ void QSelectThread::stop()
}
QSocketActiveObject::QSocketActiveObject(QEventDispatcherSymbian *dispatcher, QSocketNotifier *notifier)
- : CActive(CActive::EPriorityStandard),
- m_dispatcher(dispatcher),
+ : QActiveObject(CActive::EPriorityStandard, dispatcher),
m_notifier(notifier),
m_inSocketEvent(false),
m_deleteLater(false)
@@ -458,6 +506,9 @@ void QSocketActiveObject::DoCancel()
void QSocketActiveObject::RunL()
{
+ if (!okToRun())
+ return;
+
m_dispatcher->socketFired(this);
}
@@ -474,7 +525,7 @@ QEventDispatcherSymbian::QEventDispatcherSymbian(QObject *parent)
: QAbstractEventDispatcher(parent),
m_activeScheduler(0),
m_wakeUpAO(0),
- m_completeZeroTimersAO(0),
+ m_completeDeferredAOs(0),
m_interrupt(false),
m_wakeUpDone(0),
m_noSocketEvents(false)
@@ -493,6 +544,7 @@ void QEventDispatcherSymbian::startingUp()
CActiveScheduler::Install(m_activeScheduler);
}
m_wakeUpAO = new(ELeave) QWakeUpActiveObject(this);
+ m_completeDeferredAOs = new(ELeave) QCompleteDeferredAOs(this);
// We already might have posted events, wakeup once to process them
wakeUp();
}
@@ -503,6 +555,7 @@ void QEventDispatcherSymbian::closingDown()
m_selectThread.stop();
}
+ delete m_completeDeferredAOs;
delete m_wakeUpAO;
if (m_activeScheduler) {
delete m_activeScheduler;
@@ -703,17 +756,28 @@ bool QEventDispatcherSymbian::sendPostedEvents()
//return false;
}
-void QEventDispatcherSymbian::completeZeroTimers()
+inline void QEventDispatcherSymbian::addDeferredActiveObject(QActiveObject *object)
{
- for (QHash<int, SymbianTimerInfoPtr>::iterator i = m_timerList.begin(); i != m_timerList.end(); ++i) {
- if ((*i)->interval == 0 && (*i)->timerAO->iStatus.Int() & KRequestPending) {
- TRequestStatus *status = &(*i)->timerAO->iStatus;
- QEventDispatcherSymbian::RequestComplete(status, KErrNone);
- }
+ if (m_deferredActiveObjects.isEmpty()) {
+ m_completeDeferredAOs->complete();
+ }
+ m_deferredActiveObjects.append(object);
+}
+
+inline void QEventDispatcherSymbian::removeDeferredActiveObject(QActiveObject *object)
+{
+ m_deferredActiveObjects.removeAll(object);
+}
+
+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 zero timer once.
+ // each invocation of processEvents should only run each active object once.
// The active scheduler should run them continously, however.
m_interrupt = true;
}
@@ -776,16 +840,9 @@ void QEventDispatcherSymbian::registerTimer ( int timerId, int interval, QObject
timer->inTimerEvent = false;
timer->receiver = object;
timer->dispatcher = this;
- timer->timerAO = new(ELeave) QTimerActiveObject(timer.data());
+ timer->timerAO = new(ELeave) QTimerActiveObject(this, timer.data());
m_timerList.insert(timerId, timer);
- if (interval == 0) {
- if (!m_completeZeroTimersAO) {
- m_completeZeroTimersAO = new (ELeave) QCompleteZeroTimersActiveObject(this);
- }
- m_completeZeroTimersAO->ref();
- }
-
timer->timerAO->Start();
}
@@ -796,12 +853,6 @@ bool QEventDispatcherSymbian::unregisterTimer ( int timerId )
}
SymbianTimerInfoPtr timerInfo = m_timerList.take(timerId);
- if (timerInfo->interval == 0) {
- if (!m_completeZeroTimersAO->deref()) {
- delete m_completeZeroTimersAO;
- m_completeZeroTimersAO = 0;
- }
- }
return true;
}
diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h
index 81444729df..3233fe4214 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian_p.h
+++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h
@@ -45,6 +45,24 @@ QT_BEGIN_NAMESPACE
class QEventDispatcherSymbian;
class QTimerActiveObject;
+class QActiveObject : public CActive
+{
+public:
+ QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher);
+ ~QActiveObject();
+
+ bool okToRun();
+
+ void reactivateAndComplete();
+
+protected:
+ QEventDispatcherSymbian *m_dispatcher;
+
+private:
+ bool m_hasAlreadyRun : 1;
+ bool m_hasRunAgain : 1;
+};
+
class QWakeUpActiveObject : public CActive
{
public:
@@ -76,10 +94,10 @@ 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(SymbianTimerInfo *timerInfo);
+ QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo);
~QTimerActiveObject();
void Start();
@@ -93,25 +111,23 @@ private:
RTimer m_rTimer;
};
-class QCompleteZeroTimersActiveObject : public CActive
+class QCompleteDeferredAOs : public CActive
{
public:
- QCompleteZeroTimersActiveObject(QEventDispatcherSymbian *dispatcher);
- ~QCompleteZeroTimersActiveObject();
+ QCompleteDeferredAOs(QEventDispatcherSymbian *dispatcher);
+ ~QCompleteDeferredAOs();
- bool ref();
- bool deref();
+ void complete();
protected:
void DoCancel();
void RunL();
private:
- int m_refCount;
QEventDispatcherSymbian *m_dispatcher;
};
-class QSocketActiveObject : public CActive
+class QSocketActiveObject : public QActiveObject
{
public:
QSocketActiveObject(QEventDispatcherSymbian *dispatcher, QSocketNotifier *notifier);
@@ -124,7 +140,6 @@ protected:
void RunL();
private:
- QEventDispatcherSymbian *m_dispatcher;
QSocketNotifier *m_notifier;
bool m_inSocketEvent;
bool m_deleteLater;
@@ -187,7 +202,10 @@ public:
void socketFired(QSocketActiveObject *socketAO);
void wakeUpWasCalled();
void reactivateSocketNotifier(QSocketNotifier *notifier);
- void completeZeroTimers();
+
+ void addDeferredActiveObject(QActiveObject *object);
+ void removeDeferredActiveObject(QActiveObject *object);
+ void reactivateDeferredActiveObjects();
static void RequestComplete(TRequestStatus *&status, TInt reason);
static void RequestComplete(RThread &threadHandle, TRequestStatus *&status, TInt reason);
@@ -205,7 +223,7 @@ private:
QHash<QSocketNotifier *, QSocketActiveObject *> m_notifiers;
QWakeUpActiveObject *m_wakeUpAO;
- QCompleteZeroTimersActiveObject *m_completeZeroTimersAO;
+ QCompleteDeferredAOs *m_completeDeferredAOs;
volatile bool m_interrupt;
QAtomicInt m_wakeUpDone;
@@ -213,6 +231,8 @@ private:
bool m_noSocketEvents;
QList<QSocketActiveObject *> m_deferredSocketEvents;
+ QList<QActiveObject *> m_deferredActiveObjects;
+
RProcess m_processHandle;
};
diff --git a/tests/auto/qtimer/tst_qtimer.cpp b/tests/auto/qtimer/tst_qtimer.cpp
index 39144af0f7..0051a9b1e2 100644
--- a/tests/auto/qtimer/tst_qtimer.cpp
+++ b/tests/auto/qtimer/tst_qtimer.cpp
@@ -528,9 +528,6 @@ void tst_QTimer::timerFiresOnlyOncePerProcessEvents()
QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
}
-#ifdef Q_OS_SYMBIAN
- QEXPECT_FAIL("non-zero timer", "Will be fixed in next commit", Abort);
-#endif
QCOMPARE(longSlot.count, 1);
}