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
Reviewed-by: René J.V. Bertin <rjvbertin@gmail.com>
Reviewed-by: Anton Kudryavtsev <antkudr@mail.ru>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Thiago Macieira 2016-04-28 15:00:58 -07:00 committed by Jani Heikkinen
parent 74d79fcf1a
commit daeb334039
6 changed files with 128 additions and 94 deletions

View File

@ -190,6 +190,7 @@ void QDBusConnectionManager::run()
} }
} }
connectionHash.clear(); connectionHash.clear();
customTypes.clear();
// allow deletion from any thread without warning // allow deletion from any thread without warning
moveToThread(Q_NULLPTR); moveToThread(Q_NULLPTR);

View File

@ -55,13 +55,14 @@
#include <QtDBus/private/qtdbusglobal_p.h> #include <QtDBus/private/qtdbusglobal_p.h>
#include "qdbusconnection_p.h" #include "qdbusconnection_p.h"
#include "qdbusmetatype_p.h"
#include "private/qthread_p.h" #include "private/qthread_p.h"
#ifndef QT_NO_DBUS #ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QDBusConnectionManager : public QDaemonThread class QDBusConnectionManager : public QDaemonThread, public QDBusMetaTypeId
{ {
Q_OBJECT Q_OBJECT
struct ConnectionRequestData; struct ConnectionRequestData;

View File

@ -1036,7 +1036,6 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)
qdbusThreadDebug = qdbusDefaultThreadDebug; qdbusThreadDebug = qdbusDefaultThreadDebug;
#endif #endif
QDBusMetaTypeId::init();
connect(this, &QDBusConnectionPrivate::dispatchStatusChanged, connect(this, &QDBusConnectionPrivate::dispatchStatusChanged,
this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection); this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection);
connect(this, &QDBusConnectionPrivate::spyHooksFinished, connect(this, &QDBusConnectionPrivate::spyHooksFinished,

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the QtDBus module of the Qt Toolkit. ** This file is part of the QtDBus module of the Qt Toolkit.
@ -39,19 +40,15 @@
#include "qdbusmetatype.h" #include "qdbusmetatype.h"
#include "qdbusmetatype_p.h" #include "qdbusmetatype_p.h"
#include <string.h>
#include "qdbus_symbols_p.h" #include "qdbus_symbols_p.h"
#include <qbytearray.h> #include <string.h>
#include <qglobal.h>
#include <qreadwritelock.h>
#include <qvector.h>
#include "qdbusargument_p.h" #include "qdbusargument_p.h"
#include "qdbusutil_p.h" #include "qdbusutil_p.h"
#include "qdbusunixfiledescriptor.h" #include "qdbusunixfiledescriptor.h"
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
#include "qdbusconnectionmanager_p.h"
#include "qdbusmessage.h" #include "qdbusmessage.h"
#endif #endif
@ -64,81 +61,71 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QDBusCustomTypeInfo static void registerMarshallOperatorsNoLock(QVector<QDBusCustomTypeInfo> &ct, int id,
{ QDBusMetaType::MarshallFunction mf,
public: QDBusMetaType::DemarshallFunction df);
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;
};
template<typename T> template<typename T>
inline static void registerHelper(T * = 0) inline static void registerHelper(QVector<QDBusCustomTypeInfo> &ct)
{ {
void (*mf)(QDBusArgument &, const T *) = qDBusMarshallHelper<T>; void (*mf)(QDBusArgument &, const T *) = qDBusMarshallHelper<T>;
void (*df)(const QDBusArgument &, T *) = qDBusDemarshallHelper<T>; void (*df)(const QDBusArgument &, T *) = qDBusDemarshallHelper<T>;
QDBusMetaType::registerMarshallOperators(qMetaTypeId<T>(), registerMarshallOperatorsNoLock(ct, qMetaTypeId<T>(),
reinterpret_cast<QDBusMetaType::MarshallFunction>(mf), reinterpret_cast<QDBusMetaType::MarshallFunction>(mf),
reinterpret_cast<QDBusMetaType::DemarshallFunction>(df)); reinterpret_cast<QDBusMetaType::DemarshallFunction>(df));
} }
void QDBusMetaTypeId::init() QDBusMetaTypeId *QDBusMetaTypeId::instance()
{ {
static QBasicAtomicInt initialized = Q_BASIC_ATOMIC_INITIALIZER(false); #ifdef QT_BOOTSTRAPPED
static QDBusMetaTypeId self;
// reentrancy is not a problem since everything else is locked on their own return &self;
// set the guard variable at the end #else
if (!initialized.load()) { return QDBusConnectionManager::instance();
// register our types with Qt Core (calling qMetaTypeId<T>() 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<QDate>();
registerHelper<QTime>();
registerHelper<QDateTime>();
registerHelper<QRect>();
registerHelper<QRectF>();
registerHelper<QSize>();
registerHelper<QSizeF>();
registerHelper<QPoint>();
registerHelper<QPointF>();
registerHelper<QLine>();
registerHelper<QLineF>();
registerHelper<QVariantList>();
registerHelper<QVariantMap>();
registerHelper<QVariantHash>();
qDBusRegisterMetaType<QList<bool> >();
qDBusRegisterMetaType<QList<short> >();
qDBusRegisterMetaType<QList<ushort> >();
qDBusRegisterMetaType<QList<int> >();
qDBusRegisterMetaType<QList<uint> >();
qDBusRegisterMetaType<QList<qlonglong> >();
qDBusRegisterMetaType<QList<qulonglong> >();
qDBusRegisterMetaType<QList<double> >();
qDBusRegisterMetaType<QList<QDBusObjectPath> >();
qDBusRegisterMetaType<QList<QDBusSignature> >();
qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
#endif #endif
initialized.store(true);
}
} }
Q_GLOBAL_STATIC(QVector<QDBusCustomTypeInfo>, customTypes) QDBusMetaTypeId::QDBusMetaTypeId()
Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock) {
// register our types with Qt Core (calling qMetaTypeId<T>() 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<QDate>(customTypes);
registerHelper<QTime>(customTypes);
registerHelper<QDateTime>(customTypes);
registerHelper<QRect>(customTypes);
registerHelper<QRectF>(customTypes);
registerHelper<QSize>(customTypes);
registerHelper<QSizeF>(customTypes);
registerHelper<QPoint>(customTypes);
registerHelper<QPointF>(customTypes);
registerHelper<QLine>(customTypes);
registerHelper<QLineF>(customTypes);
registerHelper<QVariantList>(customTypes);
registerHelper<QVariantMap>(customTypes);
registerHelper<QVariantHash>(customTypes);
registerHelper<QList<bool> >(customTypes);
registerHelper<QList<short> >(customTypes);
registerHelper<QList<ushort> >(customTypes);
registerHelper<QList<int> >(customTypes);
registerHelper<QList<uint> >(customTypes);
registerHelper<QList<qlonglong> >(customTypes);
registerHelper<QList<qulonglong> >(customTypes);
registerHelper<QList<double> >(customTypes);
registerHelper<QList<QDBusObjectPath> >(customTypes);
registerHelper<QList<QDBusSignature> >(customTypes);
registerHelper<QList<QDBusUnixFileDescriptor> >(customTypes);
#endif
}
/*! /*!
\class QDBusMetaType \class QDBusMetaType
@ -217,14 +204,22 @@ void QDBusMetaType::registerMarshallOperators(int id, MarshallFunction mf,
DemarshallFunction df) DemarshallFunction df)
{ {
QByteArray var; QByteArray var;
QVector<QDBusCustomTypeInfo> *ct = customTypes(); QDBusMetaTypeId *mgr = QDBusMetaTypeId::instance();
if (id < 0 || !mf || !df || !ct) if (id < 0 || !mf || !df || !mgr)
return; // error! return; // error!
QWriteLocker locker(customTypesLock()); QWriteLocker locker(&mgr->customTypesLock);
if (id >= ct->size()) QVector<QDBusCustomTypeInfo> &ct = mgr->customTypes;
ct->resize(id + 1); registerMarshallOperatorsNoLock(ct, id, mf, df);
QDBusCustomTypeInfo &info = (*ct)[id]; }
static void registerMarshallOperatorsNoLock(QVector<QDBusCustomTypeInfo> &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.marshall = mf;
info.demarshall = df; info.demarshall = df;
} }
@ -241,12 +236,16 @@ bool QDBusMetaType::marshall(QDBusArgument &arg, int id, const void *data)
MarshallFunction mf; MarshallFunction mf;
{ {
QReadLocker locker(customTypesLock()); const QDBusMetaTypeId *mgr = QDBusMetaTypeId::instance();
QVector<QDBusCustomTypeInfo> *ct = customTypes(); if (!mgr)
if (id >= ct->size()) return false; // shutting down
QReadLocker locker(&mgr->customTypesLock);
const QVector<QDBusCustomTypeInfo> &ct = mgr->customTypes;
if (id >= ct.size())
return false; // non-existent return false; // non-existent
const QDBusCustomTypeInfo &info = (*ct).at(id); const QDBusCustomTypeInfo &info = ct.at(id);
if (!info.marshall) { if (!info.marshall) {
mf = 0; // make gcc happy mf = 0; // make gcc happy
return false; return false;
@ -270,12 +269,16 @@ bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data)
DemarshallFunction df; DemarshallFunction df;
{ {
QReadLocker locker(customTypesLock()); const QDBusMetaTypeId *mgr = QDBusMetaTypeId::instance();
QVector<QDBusCustomTypeInfo> *ct = customTypes(); if (!mgr)
if (id >= ct->size()) return false; // shutting down
QReadLocker locker(&mgr->customTypesLock);
const QVector<QDBusCustomTypeInfo> &ct = mgr->customTypes;
if (id >= ct.size())
return false; // non-existent return false; // non-existent
const QDBusCustomTypeInfo &info = (*ct).at(id); const QDBusCustomTypeInfo &info = ct.at(id);
if (!info.demarshall) { if (!info.demarshall) {
df = 0; // make gcc happy df = 0; // make gcc happy
return false; return false;
@ -434,7 +437,11 @@ const char *QDBusMetaType::typeToSignature(int type)
DBUS_TYPE_BYTE_AS_STRING; // ay 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()) if (type == QDBusMetaTypeId::variant())
return DBUS_TYPE_VARIANT_AS_STRING; return DBUS_TYPE_VARIANT_AS_STRING;
else if (type == QDBusMetaTypeId::objectpath()) else if (type == QDBusMetaTypeId::objectpath())
@ -444,14 +451,13 @@ const char *QDBusMetaType::typeToSignature(int type)
else if (type == QDBusMetaTypeId::unixfd()) else if (type == QDBusMetaTypeId::unixfd())
return DBUS_TYPE_UNIX_FD_AS_STRING; return DBUS_TYPE_UNIX_FD_AS_STRING;
// try the database
QVector<QDBusCustomTypeInfo> *ct = customTypes();
{ {
QReadLocker locker(customTypesLock()); QReadLocker locker(&mgr->customTypesLock);
if (type >= ct->size()) const QVector<QDBusCustomTypeInfo> &ct = mgr->customTypes;
if (type >= ct.size())
return 0; // type not registered with us return 0; // type not registered with us
const QDBusCustomTypeInfo &info = (*ct).at(type); const QDBusCustomTypeInfo &info = ct.at(type);
if (!info.signature.isNull()) if (!info.signature.isNull())
return info.signature; return info.signature;
@ -468,8 +474,9 @@ const char *QDBusMetaType::typeToSignature(int type)
QByteArray signature = QDBusArgumentPrivate::createSignature(type); QByteArray signature = QDBusArgumentPrivate::createSignature(type);
// re-acquire lock // re-acquire lock
QWriteLocker locker(customTypesLock()); QWriteLocker locker(&mgr->customTypesLock);
info = &(*ct)[type]; QVector<QDBusCustomTypeInfo> &ct = mgr->customTypes;
info = &ct[type];
info->signature = signature; info->signature = signature;
} }
return info->signature; return info->signature;

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the QtDBus module of the Qt Toolkit. ** This file is part of the QtDBus module of the Qt Toolkit.
@ -60,10 +61,27 @@
#include <qdbuserror.h> #include <qdbuserror.h>
#include <qdbusunixfiledescriptor.h> #include <qdbusunixfiledescriptor.h>
#include <qbytearray.h>
#include <qreadwritelock.h>
#include <qvector.h>
#ifndef QT_NO_DBUS #ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE 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 struct QDBusMetaTypeId
{ {
static int message(); // QDBusMessage static int message(); // QDBusMessage
@ -74,7 +92,14 @@ struct QDBusMetaTypeId
static int error(); // QDBusError static int error(); // QDBusError
static int unixfd(); // QDBusUnixFileDescriptor static int unixfd(); // QDBusUnixFileDescriptor
static void init(); static void init() { instance(); }
static QDBusMetaTypeId *instance();
mutable QReadWriteLock customTypesLock;
QVector<QDBusCustomTypeInfo> customTypes;
protected:
QDBusMetaTypeId();
}; };
inline int QDBusMetaTypeId::message() inline int QDBusMetaTypeId::message()

View File

@ -144,8 +144,9 @@ int qDBusParametersForMethod(const QMetaMethod &mm, QVector<int> &metaTypes, QSt
int qDBusParametersForMethod(const QList<QByteArray> &parameterTypes, QVector<int>& metaTypes, QString &errorMsg) int qDBusParametersForMethod(const QList<QByteArray> &parameterTypes, QVector<int>& metaTypes, QString &errorMsg)
{ {
QDBusMetaTypeId::init();
metaTypes.clear(); metaTypes.clear();
if (!QDBusMetaTypeId::instance())
return -1;
metaTypes.append(0); // return type metaTypes.append(0); // return type
int inputCount = 0; int inputCount = 0;