diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2011-11-30 18:56:40 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2011-11-30 18:56:40 (GMT) |
commit | bb033b56ed2cd58fd51c891e759618cbe3b02c96 (patch) | |
tree | bcbfe1251676388701029b62bf0ec9739f828fe9 /src/network | |
parent | d36732f2456569d5fde1559b717c596c7933ffeb (diff) | |
parent | 67d146092a6c11f1ca3c622ae0737202ca292a58 (diff) | |
download | Qt-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.cpp | 66 | ||||
-rw-r--r-- | src/network/bearer/qnetworkconfigmanager_p.h | 3 |
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; |