From 04cc2a3abad6ed825a97225b96a2e04f30fefcb1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 28 Apr 2016 15:00:58 -0700 Subject: [PATCH 1/2] Merge the QDBusMetaType's custom information to QDBusConnectionManager This allows us to get rid of two Q_GLOBAL_STATIC in QtDBus, which means fewer opportunities for screwing up the order of destruction. And since QDBusConnectionManager now ensures that the types are initialized, we don't need to re-initialize them everywhere. The Q_GLOBAL_STATIC for QDBusConnectionManager ensures the proper thread-safe locking, so we don't need to lock for every type that we're trying to register. This should make things faster. But as a side-effect, trying to register a D-Bus metatype will cause the QDBusConnectionManager thread to start too. Change-Id: Ifea6e497f11a461db432ffff1449a4e535234485 --- src/dbus/qdbusconnection.cpp | 1 + src/dbus/qdbusconnectionmanager_p.h | 3 +- src/dbus/qdbusintegrator.cpp | 1 - src/dbus/qdbusmetatype.cpp | 185 +++++++++++++++++++----------------- src/dbus/qdbusmetatype_p.h | 27 +++++- src/dbus/qdbusmisc.cpp | 3 +- 6 files changed, 127 insertions(+), 93 deletions(-) diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index f95cc3a..4187f19 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -182,6 +182,7 @@ void QDBusConnectionManager::run() } } connectionHash.clear(); + customTypes.clear(); // allow deletion from any thread without warning moveToThread(Q_NULLPTR); diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h index 1c7dea8..fd6cd84 100644 --- a/src/dbus/qdbusconnectionmanager_p.h +++ b/src/dbus/qdbusconnectionmanager_p.h @@ -55,13 +55,14 @@ #include #include "qdbusconnection_p.h" +#include "qdbusmetatype_p.h" #include "private/qthread_p.h" #ifndef QT_NO_DBUS QT_BEGIN_NAMESPACE -class QDBusConnectionManager : public QDaemonThread +class QDBusConnectionManager : public QDaemonThread, public QDBusMetaTypeId { Q_OBJECT struct ConnectionRequestData; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index c63fb05..19f79e9 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1036,7 +1036,6 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) qdbusThreadDebug = qdbusDefaultThreadDebug; #endif - QDBusMetaTypeId::init(); connect(this, &QDBusConnectionPrivate::dispatchStatusChanged, this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection); connect(this, &QDBusConnectionPrivate::spyHooksFinished, diff --git a/src/dbus/qdbusmetatype.cpp b/src/dbus/qdbusmetatype.cpp index fb2b407..9ab3c34 100644 --- a/src/dbus/qdbusmetatype.cpp +++ b/src/dbus/qdbusmetatype.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -39,19 +40,15 @@ #include "qdbusmetatype.h" #include "qdbusmetatype_p.h" - -#include #include "qdbus_symbols_p.h" -#include -#include -#include -#include +#include #include "qdbusargument_p.h" #include "qdbusutil_p.h" #include "qdbusunixfiledescriptor.h" #ifndef QT_BOOTSTRAPPED +#include "qdbusconnectionmanager_p.h" #include "qdbusmessage.h" #endif @@ -64,82 +61,72 @@ QT_BEGIN_NAMESPACE -class QDBusCustomTypeInfo -{ -public: - QDBusCustomTypeInfo() : signature(), marshall(0), demarshall(0) - { } - - // Suggestion: - // change 'signature' to char* and make QDBusCustomTypeInfo a Movable type - QByteArray signature; - QDBusMetaType::MarshallFunction marshall; - QDBusMetaType::DemarshallFunction demarshall; -}; +static void registerMarshallOperatorsNoLock(QVector &ct, int id, + QDBusMetaType::MarshallFunction mf, + QDBusMetaType::DemarshallFunction df); template -inline static void registerHelper(T * = 0) +inline static void registerHelper(QVector &ct) { void (*mf)(QDBusArgument &, const T *) = qDBusMarshallHelper; void (*df)(const QDBusArgument &, T *) = qDBusDemarshallHelper; - QDBusMetaType::registerMarshallOperators(qMetaTypeId(), + registerMarshallOperatorsNoLock(ct, qMetaTypeId(), reinterpret_cast(mf), reinterpret_cast(df)); } -void QDBusMetaTypeId::init() +QDBusMetaTypeId *QDBusMetaTypeId::instance() { - static QBasicAtomicInt initialized = Q_BASIC_ATOMIC_INITIALIZER(false); - - // reentrancy is not a problem since everything else is locked on their own - // set the guard variable at the end - if (!initialized.load()) { - // register our types with Qt Core (calling qMetaTypeId() does this implicitly) - (void)message(); - (void)argument(); - (void)variant(); - (void)objectpath(); - (void)signature(); - (void)error(); - (void)unixfd(); +#ifdef QT_BOOTSTRAPPED + static QDBusMetaTypeId self; + return &self; +#else + return QDBusConnectionManager::instance(); +#endif +} + +QDBusMetaTypeId::QDBusMetaTypeId() +{ + // register our types with Qt Core (calling qMetaTypeId() does this implicitly) + (void)message(); + (void)argument(); + (void)variant(); + (void)objectpath(); + (void)signature(); + (void)error(); + (void)unixfd(); #ifndef QDBUS_NO_SPECIALTYPES - // and register Qt Core's with us - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - registerHelper(); - - qDBusRegisterMetaType >(); - qDBusRegisterMetaType >(); - qDBusRegisterMetaType >(); - qDBusRegisterMetaType >(); - qDBusRegisterMetaType >(); - qDBusRegisterMetaType >(); - qDBusRegisterMetaType >(); - qDBusRegisterMetaType >(); - qDBusRegisterMetaType >(); - qDBusRegisterMetaType >(); - qDBusRegisterMetaType >(); + // and register Qt Core's with us + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + registerHelper(customTypes); + + registerHelper >(customTypes); + registerHelper >(customTypes); + registerHelper >(customTypes); + registerHelper >(customTypes); + registerHelper >(customTypes); + registerHelper >(customTypes); + registerHelper >(customTypes); + registerHelper >(customTypes); + registerHelper >(customTypes); + registerHelper >(customTypes); + registerHelper >(customTypes); #endif - - initialized.store(true); - } } -Q_GLOBAL_STATIC(QVector, customTypes) -Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock) - /*! \class QDBusMetaType \inmodule QtDBus @@ -217,14 +204,22 @@ void QDBusMetaType::registerMarshallOperators(int id, MarshallFunction mf, DemarshallFunction df) { QByteArray var; - QVector *ct = customTypes(); - if (id < 0 || !mf || !df || !ct) + QDBusMetaTypeId *mgr = QDBusMetaTypeId::instance(); + if (id < 0 || !mf || !df || !mgr) return; // error! - QWriteLocker locker(customTypesLock()); - if (id >= ct->size()) - ct->resize(id + 1); - QDBusCustomTypeInfo &info = (*ct)[id]; + QWriteLocker locker(&mgr->customTypesLock); + QVector &ct = mgr->customTypes; + registerMarshallOperatorsNoLock(ct, id, mf, df); +} + +static void registerMarshallOperatorsNoLock(QVector &ct, int id, + QDBusMetaType::MarshallFunction mf, + QDBusMetaType::DemarshallFunction df) +{ + if (id >= ct.size()) + ct.resize(id + 1); + QDBusCustomTypeInfo &info = ct[id]; info.marshall = mf; info.demarshall = df; } @@ -241,12 +236,16 @@ bool QDBusMetaType::marshall(QDBusArgument &arg, int id, const void *data) MarshallFunction mf; { - QReadLocker locker(customTypesLock()); - QVector *ct = customTypes(); - if (id >= ct->size()) + const QDBusMetaTypeId *mgr = QDBusMetaTypeId::instance(); + if (!mgr) + return false; // shutting down + + QReadLocker locker(&mgr->customTypesLock); + const QVector &ct = mgr->customTypes; + if (id >= ct.size()) return false; // non-existent - const QDBusCustomTypeInfo &info = (*ct).at(id); + const QDBusCustomTypeInfo &info = ct.at(id); if (!info.marshall) { mf = 0; // make gcc happy return false; @@ -270,12 +269,16 @@ bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data) DemarshallFunction df; { - QReadLocker locker(customTypesLock()); - QVector *ct = customTypes(); - if (id >= ct->size()) + const QDBusMetaTypeId *mgr = QDBusMetaTypeId::instance(); + if (!mgr) + return false; // shutting down + + QReadLocker locker(&mgr->customTypesLock); + const QVector &ct = mgr->customTypes; + if (id >= ct.size()) return false; // non-existent - const QDBusCustomTypeInfo &info = (*ct).at(id); + const QDBusCustomTypeInfo &info = ct.at(id); if (!info.demarshall) { df = 0; // make gcc happy return false; @@ -434,7 +437,11 @@ const char *QDBusMetaType::typeToSignature(int type) DBUS_TYPE_BYTE_AS_STRING; // ay } - QDBusMetaTypeId::init(); + // try the database + QDBusMetaTypeId *mgr = QDBusMetaTypeId::instance(); + if (!mgr) + return Q_NULLPTR; // shutting down + if (type == QDBusMetaTypeId::variant()) return DBUS_TYPE_VARIANT_AS_STRING; else if (type == QDBusMetaTypeId::objectpath()) @@ -444,14 +451,13 @@ const char *QDBusMetaType::typeToSignature(int type) else if (type == QDBusMetaTypeId::unixfd()) return DBUS_TYPE_UNIX_FD_AS_STRING; - // try the database - QVector *ct = customTypes(); { - QReadLocker locker(customTypesLock()); - if (type >= ct->size()) + QReadLocker locker(&mgr->customTypesLock); + const QVector &ct = mgr->customTypes; + if (type >= ct.size()) return 0; // type not registered with us - const QDBusCustomTypeInfo &info = (*ct).at(type); + const QDBusCustomTypeInfo &info = ct.at(type); if (!info.signature.isNull()) return info.signature; @@ -468,8 +474,9 @@ const char *QDBusMetaType::typeToSignature(int type) QByteArray signature = QDBusArgumentPrivate::createSignature(type); // re-acquire lock - QWriteLocker locker(customTypesLock()); - info = &(*ct)[type]; + QWriteLocker locker(&mgr->customTypesLock); + QVector &ct = mgr->customTypes; + info = &ct[type]; info->signature = signature; } return info->signature; diff --git a/src/dbus/qdbusmetatype_p.h b/src/dbus/qdbusmetatype_p.h index 1aa1155..1f7e613 100644 --- a/src/dbus/qdbusmetatype_p.h +++ b/src/dbus/qdbusmetatype_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -60,10 +61,27 @@ #include #include +#include +#include +#include + #ifndef QT_NO_DBUS QT_BEGIN_NAMESPACE +class QDBusCustomTypeInfo +{ +public: + QDBusCustomTypeInfo() : signature(), marshall(0), demarshall(0) + { } + + // Suggestion: + // change 'signature' to char* and make QDBusCustomTypeInfo a Movable type + QByteArray signature; + QDBusMetaType::MarshallFunction marshall; + QDBusMetaType::DemarshallFunction demarshall; +}; + struct QDBusMetaTypeId { static int message(); // QDBusMessage @@ -74,7 +92,14 @@ struct QDBusMetaTypeId static int error(); // QDBusError static int unixfd(); // QDBusUnixFileDescriptor - static void init(); + static void init() { instance(); } + static QDBusMetaTypeId *instance(); + + mutable QReadWriteLock customTypesLock; + QVector customTypes; + +protected: + QDBusMetaTypeId(); }; inline int QDBusMetaTypeId::message() diff --git a/src/dbus/qdbusmisc.cpp b/src/dbus/qdbusmisc.cpp index 930c3bd..01436da 100644 --- a/src/dbus/qdbusmisc.cpp +++ b/src/dbus/qdbusmisc.cpp @@ -144,8 +144,9 @@ int qDBusParametersForMethod(const QMetaMethod &mm, QVector &metaTypes, QSt int qDBusParametersForMethod(const QList ¶meterTypes, QVector& metaTypes, QString &errorMsg) { - QDBusMetaTypeId::init(); metaTypes.clear(); + if (!QDBusMetaTypeId::instance()) + return -1; metaTypes.append(0); // return type int inputCount = 0; -- 2.9.3