Remove refcounting of QMetaTypeInterface

It's only used for dynamic types in DBUS and QML, where we control
things good enough to be able to handle the lifetime of those
interfaces there.

Change-Id: Ia7f8970d17a85b195db85fcdc2d8f1febd8753f4
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Lars Knoll 2020-07-15 21:21:05 +02:00
parent d0ccb3aaf9
commit 92b3767632
7 changed files with 25 additions and 83 deletions

View File

@ -779,13 +779,16 @@ bool QMetaType::isOrdered() const
return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->lessThan != nullptr);
}
void QtMetaTypePrivate::derefAndDestroy(NS(QtPrivate::QMetaTypeInterface) *d_ptr)
/*!
\internal
*/
void QMetaType::unregisterMetaType(QMetaType type)
{
if (d_ptr && !d_ptr->ref.deref()) {
if (type.d_ptr && type.d_ptr->typeId.loadRelaxed() >= QMetaType::User) {
if (auto reg = customTypeRegistry())
reg->unregisterDynamicType(d_ptr->typeId.loadRelaxed());
Q_ASSERT(d_ptr->deleteSelf);
d_ptr->deleteSelf(d_ptr);
reg->unregisterDynamicType(type.d_ptr->typeId.loadRelaxed());
type.d_ptr->typeId.storeRelease(0);
}
}
@ -794,25 +797,7 @@ void QtMetaTypePrivate::derefAndDestroy(NS(QtPrivate::QMetaTypeInterface) *d_ptr
Destructs this object.
*/
QMetaType::~QMetaType()
{
QtMetaTypePrivate::derefAndDestroy(d_ptr);
}
QMetaType::QMetaType(QtPrivate::QMetaTypeInterface *d) : d_ptr(d)
{
if (d_ptr)
d_ptr->ref.ref();
}
QMetaType &QMetaType::operator=(const QMetaType &other)
{
if (d_ptr != other.d_ptr) {
this->~QMetaType();
new (this) QMetaType(other.d_ptr);
}
return *this;
}
/*!
\fn template<typename T> QMetaType QMetaType::fromType()

View File

@ -377,17 +377,8 @@ public:
static void destruct(int type, void *where);
explicit QMetaType(int type);
explicit QMetaType(QtPrivate::QMetaTypeInterface *d);
constexpr QMetaType() : d_ptr(nullptr) {}
~QMetaType();
QMetaType(const QMetaType &other) : QMetaType(other.d_ptr) {}
QMetaType &operator=(const QMetaType &);
QMetaType(QMetaType &&other) : d_ptr(other.d_ptr) { other.d_ptr = nullptr; }
QMetaType &operator=(QMetaType &&other)
{
qSwap(d_ptr, other.d_ptr);
return *this;
}
explicit constexpr QMetaType(QtPrivate::QMetaTypeInterface *d) : d_ptr(d) {}
constexpr QMetaType() = default;
bool isValid() const;
bool isRegistered() const;
@ -566,6 +557,10 @@ public:
#endif
static bool registerConverterFunction(const ConverterFunction &f, int from, int to);
static void unregisterConverterFunction(int from, int to);
static void unregisterMetaType(QMetaType type);
QtPrivate::QMetaTypeInterface *iface() { return d_ptr; }
private:
friend class QVariant;
QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
@ -1922,20 +1917,14 @@ namespace QtPrivate {
class QMetaTypeInterface
{
public:
uint revision; // 0 in Qt 6.0. Can increase if new field are added
ushort revision; // 0 in Qt 6.0. Can increase if new field are added
ushort alignment;
uint size;
uint alignment;
uint flags;
QBasicAtomicInt typeId;
const QMetaObject *metaObject;
const char *name;
QBasicAtomicInt typeId;
QtPrivate::RefCount ref;
// Called when the type is unregistered, to delete this
using DeleteSelf = void (*)(QMetaTypeInterface *);
DeleteSelf deleteSelf;
using DefaultCtrFn = void (*)(const QMetaTypeInterface *, void *);
DefaultCtrFn defaultCtr;
using CopyCtrFn = void (*)(const QMetaTypeInterface *, void *, const void *);
@ -2504,14 +2493,12 @@ public:
template<typename T>
QMetaTypeInterface QMetaTypeForType<T>::metaType = {
/*.revision=*/ 0,
/*.size=*/ sizeof(T),
/*.alignment=*/ alignof(T),
/*.size=*/ sizeof(T),
/*.flags=*/ QMetaTypeTypeFlags<T>::Flags,
/*.typeId=*/ BuiltinMetaType<T>::value,
/*.metaObject=*/ MetaObjectForType<T>::value(),
/*.name=*/ getName(),
/*.typeId=*/ BuiltinMetaType<T>::value,
/*.ref=*/ Q_REFCOUNT_INITIALIZE_STATIC,
/*.deleteSelf=*/ nullptr,
/*.defaultCtr=*/ getDefaultCtr<T>(),
/*.copyCtr=*/ getCopyCtr<T>(),
/*.moveCtr=*/ getMoveCtr<T>(),
@ -2536,14 +2523,12 @@ public:
static inline QMetaTypeInterface metaType =
{
/*.revision=*/ 0,
/*.size=*/ 0,
/*.alignment=*/ 0,
/*.size=*/ 0,
/*.flags=*/ 0,
/*.typeId=*/ BuiltinMetaType<void>::value,
/*.metaObject=*/ nullptr,
/*.name=*/ "void",
/*.typeId=*/ BuiltinMetaType<void>::value,
/*.ref=*/ Q_REFCOUNT_INITIALIZE_STATIC,
/*.deleteSelf=*/ nullptr,
/*.defaultCtr=*/ nullptr,
/*.copyCtr=*/ nullptr,
/*.moveCtr=*/ nullptr,

View File

@ -233,8 +233,6 @@ static QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *getInterfaceFromType
case QMetaType::MetaTypeName: \
return QtMetaTypePrivate::getInterfaceFromType<RealName>();
void derefAndDestroy(QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *d_ptr);
} //namespace QtMetaTypePrivate
QT_END_NAMESPACE

View File

@ -3201,10 +3201,4 @@ QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::opera
return const_iterator(impl, new QAtomicInt(0));
}
QVariant::Private::~Private()
{
QtMetaTypePrivate::derefAndDestroy(
reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2));
}
QT_END_NAMESPACE

View File

@ -426,28 +426,11 @@ class Q_CORE_EXPORT QVariant
Private() noexcept : is_shared(false), is_null(true), packedType(0) {}
explicit Private(const QMetaType &type) noexcept : is_shared(false), is_null(false)
{
if (type.d_ptr)
type.d_ptr->ref.ref();
quintptr mt = quintptr(type.d_ptr);
Q_ASSERT((mt & 0x3) == 0);
packedType = mt >> 2;
}
explicit Private(int type) noexcept : Private(QMetaType(type)) {}
Private(const Private &other) : Private(other.type())
{
data = other.data;
is_shared = other.is_shared;
is_null = other.is_null;
}
Private &operator=(const Private &other)
{
if (&other != this) {
this->~Private();
new (this) Private(other);
}
return *this;
}
Q_CORE_EXPORT ~Private();
const void *storage() const
{ return is_shared ? data.shared->data() : &data.data; }

View File

@ -414,9 +414,7 @@ void tst_QMetaType::registerGadget(const char *name, const QList<GadgetPropertyT
const auto flags = QMetaType::IsGadget | QMetaType::NeedsConstruction | QMetaType::NeedsDestruction;
using TypeInfo = QtPrivate::QMetaTypeInterface;
auto typeInfo = new TypeInfo {
0, sizeof(GenericGadgetType), alignof(GenericGadgetType), uint(flags), meta, name, 0,
QtPrivate::RefCount{ 0 },
[](TypeInfo *self) { delete self; },
0, alignof(GenericGadgetType), sizeof(GenericGadgetType), uint(flags), 0, meta, name,
[](const TypeInfo *self, void *where) { GadgetTypedConstructor(self->typeId, where, nullptr); },
[](const TypeInfo *self, void *where, const void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
[](const TypeInfo *self, void *where, void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
@ -1322,9 +1320,7 @@ void tst_QMetaType::typedConstruct()
const auto flags = QMetaType::NeedsConstruction | QMetaType::NeedsDestruction;
using TypeInfo = QtPrivate::QMetaTypeInterface;
auto typeInfo = new TypeInfo {
0, sizeof(GenericGadgetType), alignof(GenericGadgetType), uint(flags), nullptr, podTypeName,
0, QtPrivate::RefCount{0},
[](TypeInfo *self) { delete self; },
0, alignof(GenericGadgetType), sizeof(GenericGadgetType), uint(flags), 0, nullptr, podTypeName,
[](const TypeInfo *self, void *where) { GadgetTypedConstructor(self->typeId, where, nullptr); },
[](const TypeInfo *self, void *where, const void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
[](const TypeInfo *self, void *where, void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },

View File

@ -1711,7 +1711,8 @@ void tst_QVariant::typeName_data()
QTest::newRow("20") << int(QVariant::Region) << QByteArray("QRegion");
QTest::newRow("21") << int(QVariant::Bitmap) << QByteArray("QBitmap");
QTest::newRow("22") << int(QVariant::Cursor) << QByteArray("QCursor");
QTest::newRow("23") << int(QVariant::SizePolicy) << QByteArray("QSizePolicy");
// The test below doesn't work as long as we don't link against widgets
// QTest::newRow("23") << int(QVariant::SizePolicy) << QByteArray("QSizePolicy");
QTest::newRow("24") << int(QVariant::Date) << QByteArray("QDate");
QTest::newRow("25") << int(QVariant::Time) << QByteArray("QTime");
QTest::newRow("26") << int(QVariant::DateTime) << QByteArray("QDateTime");