summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2011-11-30 18:56:40 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2011-11-30 18:56:40 (GMT)
commitbb033b56ed2cd58fd51c891e759618cbe3b02c96 (patch)
treebcbfe1251676388701029b62bf0ec9739f828fe9 /src/network
parentd36732f2456569d5fde1559b717c596c7933ffeb (diff)
parent67d146092a6c11f1ca3c622ae0737202ca292a58 (diff)
downloadQt-bb033b56ed2cd58fd51c891e759618cbe3b02c96.zip
Qt-bb033b56ed2cd58fd51c891e759618cbe3b02c96.tar.gz
Qt-bb033b56ed2cd58fd51c891e759618cbe3b02c96.tar.bz2
Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt-earth-staging into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/qt-earth-staging: Backport SMP safe initialisation of QNetworkConfigurationManager
Diffstat (limited to 'src/network')
-rw-r--r--src/network/bearer/qnetworkconfigmanager.cpp66
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.h3
2 files changed, 47 insertions, 22 deletions
diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp
index 8065025..da09a9c 100644
--- a/src/network/bearer/qnetworkconfigmanager.cpp
+++ b/src/network/bearer/qnetworkconfigmanager.cpp
@@ -46,34 +46,56 @@
#include <QtCore/qstringlist.h>
#include <QtCore/qcoreapplication.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qthread.h>
+#include <QtCore/private/qcoreapplication_p.h>
#ifndef QT_NO_BEARERMANAGEMENT
QT_BEGIN_NAMESPACE
-#define Q_GLOBAL_STATIC_QAPP_DESTRUCTION(TYPE, NAME) \
- static QGlobalStatic<TYPE > this_##NAME \
- = { Q_BASIC_ATOMIC_INITIALIZER(0), false }; \
- static void NAME##_cleanup() \
- { \
- this_##NAME.pointer->cleanup(); \
- this_##NAME.pointer = 0; \
- } \
- static TYPE *NAME() \
- { \
- if (!this_##NAME.pointer) { \
- TYPE *x = new TYPE; \
- if (!this_##NAME.pointer.testAndSetOrdered(0, x)) \
- delete x; \
- else { \
- qAddPostRoutine(NAME##_cleanup); \
- this_##NAME.pointer->initialize(); \
- } \
- } \
- return this_##NAME.pointer; \
- }
+static QBasicAtomicPointer<QNetworkConfigurationManagerPrivate> connManager_ptr;
+Q_GLOBAL_STATIC(QMutex, connManager_mutex)
+
+static void connManager_cleanup()
+{
+ // this is not atomic or thread-safe!
+ if(connManager_ptr)
+ connManager_ptr->cleanup();
+ connManager_ptr = 0;
+}
+
+void QNetworkConfigurationManagerPrivate::addPostRoutine()
+{
+ qAddPostRoutine(connManager_cleanup);
+}
-Q_GLOBAL_STATIC_QAPP_DESTRUCTION(QNetworkConfigurationManagerPrivate, connManager);
+static QNetworkConfigurationManagerPrivate *connManager()
+{
+ QNetworkConfigurationManagerPrivate *ptr = connManager_ptr.fetchAndAddAcquire(0);
+ if (!ptr) {
+ QMutexLocker locker(connManager_mutex());
+ if (!(ptr = connManager_ptr.fetchAndAddAcquire(0))) {
+ ptr = new QNetworkConfigurationManagerPrivate;
+
+ if (QCoreApplicationPrivate::mainThread() == QThread::currentThread()) {
+ // right thread or no main thread yet
+ ptr->addPostRoutine();
+ ptr->initialize();
+ } else {
+ // wrong thread, we need to make the main thread do this
+ QObject *obj = new QObject;
+ QObject::connect(obj, SIGNAL(destroyed()), ptr, SLOT(addPostRoutine()), Qt::DirectConnection);
+ ptr->initialize(); // this moves us to the right thread
+ obj->moveToThread(QCoreApplicationPrivate::mainThread());
+ obj->deleteLater();
+ }
+
+ connManager_ptr.fetchAndStoreRelease(ptr);
+ }
+ }
+ return ptr;
+}
QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate()
{
diff --git a/src/network/bearer/qnetworkconfigmanager_p.h b/src/network/bearer/qnetworkconfigmanager_p.h
index 56f66b4..ded1701 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.h
+++ b/src/network/bearer/qnetworkconfigmanager_p.h
@@ -94,6 +94,8 @@ public:
public Q_SLOTS:
void updateConfigurations();
+ static void addPostRoutine();
+
Q_SIGNALS:
void configurationAdded(const QNetworkConfiguration &config);
void configurationRemoved(const QNetworkConfiguration &config);
@@ -108,6 +110,7 @@ private Q_SLOTS:
void pollEngines();
+
private:
Q_INVOKABLE void startPolling();
QTimer *pollTimer;