summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShane Kearns <shane.kearns@accenture.com>2011-06-01 15:35:43 (GMT)
committerShane Kearns <shane.kearns@accenture.com>2011-06-13 11:37:51 (GMT)
commit5f879c55e531165cc2569b03c3796d0f33d0a0b7 (patch)
tree892a26d3783e9cdaedc5eec5a5e13475c07cb08d /src
parentefba403423db53ed480bd88be4dcd650f8ae831a (diff)
downloadQt-5f879c55e531165cc2569b03c3796d0f33d0a0b7.zip
Qt-5f879c55e531165cc2569b03c3796d0f33d0a0b7.tar.gz
Qt-5f879c55e531165cc2569b03c3796d0f33d0a0b7.tar.bz2
bearer: run the bearer engines in their own worker thread
The original architecture of the QtNetwork bearer support hosted the engines in the application's main thread, but this causes some problems. If the QNetworkConfigurationManager is constructed in a worker thread, then it is populated asynchronously without any notification when it is done (the app gets incomplete or missing results) Fixing that by restoring the earlier behaviour of using blocking queued connections to wait for the lists to be populated caused a regression, as some applications deadlock because the main thread is waiting on the worker thread at this time. By introducing a dedicated worker thread for the bearer engines, QNetworkConfigurationManager can be safely constructed in any thread while using blocking queued connections internally. Task-number: QTBUG-18795 Reviewed-by: mread
Diffstat (limited to 'src')
-rw-r--r--src/network/bearer/qnetworkconfigmanager.cpp4
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.cpp36
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.h3
3 files changed, 27 insertions, 16 deletions
diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp
index 65a15d7..d2c7317 100644
--- a/src/network/bearer/qnetworkconfigmanager.cpp
+++ b/src/network/bearer/qnetworkconfigmanager.cpp
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC_INIT(TYPE, NAME); \
static void NAME##_cleanup() \
{ \
- delete this_##NAME.pointer; \
+ this_##NAME.pointer->cleanup(); \
this_##NAME.pointer = 0; \
} \
static TYPE *NAME() \
@@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
delete x; \
else { \
qAddPostRoutine(NAME##_cleanup); \
- this_##NAME.pointer->updateConfigurations(); \
+ this_##NAME.pointer->initialize(); \
} \
} \
return this_##NAME.pointer; \
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
index 2391a34..17e47bd 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.cpp
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -66,11 +66,31 @@ QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
qRegisterMetaType<QNetworkConfigurationPrivatePointer>("QNetworkConfigurationPrivatePointer");
}
+void QNetworkConfigurationManagerPrivate::initialize()
+{
+ //Two stage construction, because we only want to do this heavyweight work for the winner of the Q_GLOBAL_STATIC race.
+ bearerThread = new QThread();
+ bearerThread->moveToThread(QCoreApplicationPrivate::mainThread()); // because cleanup() is called in main thread context.
+ moveToThread(bearerThread);
+ bearerThread->start();
+ updateConfigurations();
+}
+
QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate()
{
QMutexLocker locker(&mutex);
qDeleteAll(sessionEngines);
+ if (bearerThread)
+ bearerThread->quit();
+}
+
+void QNetworkConfigurationManagerPrivate::cleanup()
+{
+ QThread* thread = bearerThread;
+ deleteLater();
+ if(thread->wait(5000))
+ delete thread;
}
QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration()
@@ -356,13 +376,6 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
if (sender())
return;
- if (thread() != QCoreApplicationPrivate::mainThread()) {
- if (thread() != QThread::currentThread())
- return;
-
- moveToThread(QCoreApplicationPrivate::mainThread());
- }
-
updating = false;
#ifndef QT_NO_LIBRARY
@@ -382,7 +395,7 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
else
sessionEngines.append(engine);
- engine->moveToThread(QCoreApplicationPrivate::mainThread());
+ engine->moveToThread(bearerThread);
connect(engine, SIGNAL(updateCompleted()),
this, SLOT(updateConfigurations()));
@@ -424,14 +437,9 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
if (firstUpdate) {
firstUpdate = false;
QList<QBearerEngine*> enginesToInitialize = sessionEngines; //shallow copy the list in case it is modified when we unlock mutex
- Qt::ConnectionType connectionType;
- if (QCoreApplicationPrivate::mainThread() == QThread::currentThread())
- connectionType = Qt::DirectConnection;
- else
- connectionType = Qt::BlockingQueuedConnection;
locker.unlock();
foreach (QBearerEngine* engine, enginesToInitialize) {
- QMetaObject::invokeMethod(engine, "initialize", connectionType);
+ QMetaObject::invokeMethod(engine, "initialize", Qt::BlockingQueuedConnection);
}
}
}
diff --git a/src/network/bearer/qnetworkconfigmanager_p.h b/src/network/bearer/qnetworkconfigmanager_p.h
index 1679c3b..b3c83bc 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.h
+++ b/src/network/bearer/qnetworkconfigmanager_p.h
@@ -91,6 +91,8 @@ public:
void enablePolling();
void disablePolling();
+ void initialize();
+ void cleanup();
public slots:
void updateConfigurations();
@@ -105,6 +107,7 @@ Q_SIGNALS:
private:
QTimer *pollTimer;
+ QThread *bearerThread;
QMutex mutex;