summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShane Kearns <shane.kearns@accenture.com>2011-03-16 18:59:45 (GMT)
committerShane Kearns <shane.kearns@accenture.com>2011-03-17 14:57:50 (GMT)
commit1adef92e1b1ba9872c9676efd701eb0fd0a3a907 (patch)
tree03bbbf809ce7e65474e39fd752de5147544940a8
parent13f415e7d54ef8e2aaccabfb04f29ccfde0520df (diff)
downloadQt-1adef92e1b1ba9872c9676efd701eb0fd0a3a907.zip
Qt-1adef92e1b1ba9872c9676efd701eb0fd0a3a907.tar.gz
Qt-1adef92e1b1ba9872c9676efd701eb0fd0a3a907.tar.bz2
Implement QEventLoop::ExcludeSocketNotifiers for symbian socket engine
As the symbian socket engine is driven by an active object in the QtNetwork dll, this needs to hook into the event dispatcher in the QtCore dll. The QActiveObject base class is now a private export from QtCore The method of deferring socket events now works with any kind of QActiveObject, and not only the QSocketActiveObject (which handles "open C" sockets) The base class has a new function, to check if socket events are blocked. If so, it adds the active object to the deferred queue. The derived class should return from it's RunL in this case, which will be called again later. (same usage as the maybeQueueForLater function) reactivateAndComplete function in the event dispatcher is changed to complete the active object again with the same status code as originally. Previously it always used KErrNone, which is not ok for QAsyncSelect as it needs to check the error code from the asynchronous call. Reviewed-by: Markus Goetz Reviewed-by: mread
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp79
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian_p.h13
-rw-r--r--src/network/socket/qsymbiansocketengine.cpp28
-rw-r--r--src/network/socket/qsymbiansocketengine_p.h4
4 files changed, 77 insertions, 47 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index b074ab4..a95e7d5 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian.cpp
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -134,7 +134,7 @@ private:
* 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)
+QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher)
: CActive(priority),
m_dispatcher(dispatcher),
m_hasAlreadyRun(false),
@@ -166,12 +166,25 @@ bool QActiveObject::maybeQueueForLater()
}
}
+bool QActiveObject::maybeDeferSocketEvent()
+{
+ Q_ASSERT(!m_hasRunAgain);
+ Q_ASSERT(m_dispatcher);
+ if (!m_dispatcher->areSocketEventsBlocked()) {
+ return false;
+ }
+ m_hasRunAgain = true;
+ m_dispatcher->addDeferredSocketActiveObject(this);
+ return true;
+}
+
void QActiveObject::reactivateAndComplete()
{
+ TInt error = iStatus.Int();
iStatus = KRequestPending;
SetActive();
TRequestStatus *status = &iStatus;
- QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ QEventDispatcherSymbian::RequestComplete(status, error);
m_hasRunAgain = false;
m_hasAlreadyRun = false;
@@ -634,10 +647,28 @@ void QSocketActiveObject::DoCancel()
void QSocketActiveObject::RunL()
{
+ if (maybeDeferSocketEvent())
+ return;
if (maybeQueueForLater())
return;
- QT_TRYCATCH_LEAVING(m_dispatcher->socketFired(this));
+ QT_TRYCATCH_LEAVING(run());
+}
+
+void QSocketActiveObject::run()
+{
+ QEvent e(QEvent::SockAct);
+ m_inSocketEvent = true;
+ QCoreApplication::sendEvent(m_notifier, &e);
+ m_inSocketEvent = false;
+
+ if (m_deleteLater) {
+ delete this;
+ } else {
+ iStatus = KRequestPending;
+ SetActive();
+ m_dispatcher->reactivateSocketNotifier(m_notifier);
+ }
}
void QSocketActiveObject::deleteLater()
@@ -912,27 +943,6 @@ void QEventDispatcherSymbian::timerFired(int timerId)
return;
}
-void QEventDispatcherSymbian::socketFired(QSocketActiveObject *socketAO)
-{
- if (m_noSocketEvents) {
- m_deferredSocketEvents.append(socketAO);
- return;
- }
-
- QEvent e(QEvent::SockAct);
- socketAO->m_inSocketEvent = true;
- QCoreApplication::sendEvent(socketAO->m_notifier, &e);
- socketAO->m_inSocketEvent = false;
-
- if (socketAO->m_deleteLater) {
- delete socketAO;
- } else {
- socketAO->iStatus = KRequestPending;
- socketAO->SetActive();
- reactivateSocketNotifier(socketAO->m_notifier);
- }
-}
-
void QEventDispatcherSymbian::wakeUpWasCalled()
{
// The reactivation should happen in RunL, right before the call to this function.
@@ -993,6 +1003,12 @@ inline void QEventDispatcherSymbian::addDeferredActiveObject(QActiveObject *obje
inline void QEventDispatcherSymbian::removeDeferredActiveObject(QActiveObject *object)
{
m_deferredActiveObjects.removeAll(object);
+ m_deferredSocketEvents.removeAll(object);
+}
+
+inline void QEventDispatcherSymbian::addDeferredSocketActiveObject(QActiveObject *object)
+{
+ m_deferredSocketEvents.append(object);
}
void QEventDispatcherSymbian::queueDeferredActiveObjectsCompletion()
@@ -1018,7 +1034,8 @@ bool QEventDispatcherSymbian::sendDeferredSocketEvents()
bool sentAnyEvents = false;
while (!m_deferredSocketEvents.isEmpty()) {
sentAnyEvents = true;
- socketFired(m_deferredSocketEvents.takeFirst());
+ QActiveObject *object = m_deferredSocketEvents.takeFirst();
+ object->reactivateAndComplete();
}
return sentAnyEvents;
@@ -1037,17 +1054,18 @@ bool QEventDispatcherSymbian::hasPendingEvents()
void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifier )
{
- //TODO: just need to be able to do something when event loop has sockets disabled
-/* QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier);
+ //note - this is only for "open C" file descriptors
+ //for native sockets, an active object in the symbian socket engine handles this
+ QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier);
Q_CHECK_PTR(socketAO);
m_notifiers.insert(notifier, socketAO);
- selectThread().requestSocketEvents(notifier, &socketAO->iStatus);*/
+ selectThread().requestSocketEvents(notifier, &socketAO->iStatus);
}
void QEventDispatcherSymbian::unregisterSocketNotifier ( QSocketNotifier * notifier )
{
- //TODO: just need to be able to do something when event loop has sockets disabled
- /*
+ //note - this is only for "open C" file descriptors
+ //for native sockets, an active object in the symbian socket engine handles this
if (m_selectThread)
m_selectThread->cancelSocketEvents(notifier);
if (m_notifiers.contains(notifier)) {
@@ -1056,7 +1074,6 @@ void QEventDispatcherSymbian::unregisterSocketNotifier ( QSocketNotifier * notif
sockObj->deleteLater();
m_notifiers.remove(notifier);
}
- */
}
void QEventDispatcherSymbian::reactivateSocketNotifier(QSocketNotifier *notifier)
diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h
index bf28144..e07d475 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian_p.h
+++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h
@@ -77,13 +77,14 @@ QT_BEGIN_NAMESPACE
class QEventDispatcherSymbian;
class QTimerActiveObject;
-class Q_AUTOTEST_EXPORT QActiveObject : public CActive
+class Q_CORE_EXPORT QActiveObject : public CActive
{
public:
QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher);
~QActiveObject();
bool maybeQueueForLater();
+ bool maybeDeferSocketEvent();
void reactivateAndComplete();
@@ -176,6 +177,7 @@ public:
protected:
void DoCancel();
void RunL();
+ void run();
private:
QSocketNotifier *m_notifier;
@@ -244,7 +246,6 @@ public:
void closingDown();
void timerFired(int timerId);
- void socketFired(QSocketActiveObject *socketAO);
void wakeUpWasCalled();
void reactivateSocketNotifier(QSocketNotifier *notifier);
@@ -256,6 +257,9 @@ public:
inline int iterationCount() const { return m_iterationCount; }
+ void addDeferredSocketActiveObject(QActiveObject *object);
+ inline bool areSocketEventsBlocked() const { return m_noSocketEvents; }
+
static void RequestComplete(TRequestStatus *&status, TInt reason);
static void RequestComplete(RThread &threadHandle, TRequestStatus *&status, TInt reason);
@@ -281,8 +285,9 @@ private:
unsigned char m_iterationCount;
bool m_insideTimerEvent;
bool m_noSocketEvents;
- QList<QSocketActiveObject *> m_deferredSocketEvents;
-
+ //deferred until socket events are enabled
+ QList<QActiveObject *> m_deferredSocketEvents;
+ //deferred until idle
QList<QActiveObject *> m_deferredActiveObjects;
int m_delay;
diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp
index 688f724..07b2e5a 100644
--- a/src/network/socket/qsymbiansocketengine.cpp
+++ b/src/network/socket/qsymbiansocketengine.cpp
@@ -63,6 +63,7 @@
#include <QCoreApplication>
#include <qabstracteventdispatcher.h>
+#include <private/qeventdispatcher_symbian_p.h>
#include <qsocketnotifier.h>
#include <qnetworkinterface.h>
@@ -187,7 +188,6 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so
TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp;
//Check if there is a user specified session
- RConnection *connection = 0;
QVariant v(q->property("_q_networksession"));
TInt err;
if (v.isValid()) {
@@ -1437,7 +1437,9 @@ void QSymbianSocketEngine::setReadNotificationEnabled(bool enable)
#endif
d->readNotificationsEnabled = enable;
if (enable && d->threadData->eventDispatcher && !d->asyncSelect)
- d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this));
+ d->asyncSelect = q_check_ptr(
+ new QAsyncSelect(static_cast<QEventDispatcherSymbian*>(d->threadData->eventDispatcher),
+ d->nativeSocket, this));
// TODO: what do we do if event dispatcher doesn't exist yet?
if (d->asyncSelect)
d->asyncSelect->IssueRequest();
@@ -1459,7 +1461,9 @@ void QSymbianSocketEngine::setWriteNotificationEnabled(bool enable)
#endif
d->writeNotificationsEnabled = enable;
if (enable && d->threadData->eventDispatcher && !d->asyncSelect)
- d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this));
+ d->asyncSelect = q_check_ptr(
+ new QAsyncSelect(static_cast<QEventDispatcherSymbian*>(d->threadData->eventDispatcher),
+ d->nativeSocket, this));
// TODO: what do we do if event dispatcher doesn't exist yet?
if (d->asyncSelect)
d->asyncSelect->IssueRequest();
@@ -1483,7 +1487,9 @@ void QSymbianSocketEngine::setExceptionNotificationEnabled(bool enable)
#endif
d->exceptNotificationsEnabled = enable;
if (enable && d->threadData->eventDispatcher && !d->asyncSelect)
- d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this));
+ d->asyncSelect = q_check_ptr(
+ new QAsyncSelect(static_cast<QEventDispatcherSymbian*>(d->threadData->eventDispatcher),
+ d->nativeSocket, this));
if (d->asyncSelect)
d->asyncSelect->IssueRequest();
}
@@ -1597,15 +1603,17 @@ bool QSymbianSocketEngine::event(QEvent* ev)
qDebug() << "PostThreadChangeEvent" << d->readNotificationsEnabled << d->writeNotificationsEnabled << d->exceptNotificationsEnabled;
#endif
// recreate select in new thread
- d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this));
+ d->asyncSelect = q_check_ptr(
+ new QAsyncSelect(static_cast<QEventDispatcherSymbian*>(d->threadData->eventDispatcher),
+ d->nativeSocket, this));
d->asyncSelect->IssueRequest();
return true;
}
return QAbstractSocketEngine::event(ev);
}
-QAsyncSelect::QAsyncSelect(QAbstractEventDispatcher *dispatcher, RSocket& sock, QSymbianSocketEngine *parent)
- : CActive(CActive::EPriorityStandard),
+QAsyncSelect::QAsyncSelect(QEventDispatcherSymbian *dispatcher, RSocket& sock, QSymbianSocketEngine *parent)
+ : QActiveObject(CActive::EPriorityStandard, dispatcher),
m_inSocketEvent(false),
m_deleteLater(false),
m_socket(sock),
@@ -1652,9 +1660,9 @@ TInt QAsyncSelect::RunError(TInt aError)
void QAsyncSelect::run()
{
- //TODO: block when event loop demands it
- //if (maybeQueueForLater())
- // return;
+ //when event loop disabled socket events, defer until later
+ if (maybeDeferSocketEvent())
+ return;
m_inSocketEvent = true;
m_selectBuf() &= m_selectFlags; //the select ioctl reports everything, so mask to only what we requested
//KSockSelectReadContinuation is for reading datagrams in a mode that doesn't discard when the
diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h
index 432e4dc..bbe1269 100644
--- a/src/network/socket/qsymbiansocketengine_p.h
+++ b/src/network/socket/qsymbiansocketengine_p.h
@@ -151,10 +151,10 @@ class QSocketNotifier;
class QReadNotifier;
class QWriteNotifier;
class QExceptionNotifier;
-class QAsyncSelect : public CActive
+class QAsyncSelect : public QActiveObject
{
public:
- QAsyncSelect(QAbstractEventDispatcher *dispatcher, RSocket& sock, QSymbianSocketEngine *parent);
+ QAsyncSelect(QEventDispatcherSymbian *dispatcher, RSocket& sock, QSymbianSocketEngine *parent);
~QAsyncSelect();
void deleteLater();