Allow QMetaType to register information about movability
We need that information to perform some optimizations in QVariant. Change-Id: Id9a1716e49e4cedd17cd09a32fea4ff003ef61f2 Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
This commit is contained in:
parent
d868c9945a
commit
56f154c747
@ -239,6 +239,16 @@ template<> struct TypeDefiniton<QRegExp> { static const bool IsAvailable = false
|
||||
\sa type(), typeName()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QMetaType::TypeFlags
|
||||
|
||||
The enum describes attributes of a type supported by QMetaType.
|
||||
|
||||
\value NeedsConstruction This type has non-trivial constructors. If the flag is not set instances can be safely initialized with memset to 0.
|
||||
\value NeedsDestruction This type has a non-trivial destructor. If the flag is not set calls to the destructor are not necessary before discarding objects.
|
||||
\value MovableType An instance of a type having this attribute can be safely moved by memcpy.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QMetaType
|
||||
\brief The QMetaType class manages named types in the meta-object system.
|
||||
@ -423,7 +433,7 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
|
||||
int QMetaType::registerType(const char *typeName, Deleter deleter,
|
||||
Creator creator)
|
||||
{
|
||||
return registerType(typeName, deleter, creator, 0, 0, 0);
|
||||
return registerType(typeName, deleter, creator, 0, 0, 0, TypeFlags());
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
@ -438,7 +448,7 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
|
||||
Creator creator,
|
||||
Destructor destructor,
|
||||
Constructor constructor,
|
||||
int size)
|
||||
int size, TypeFlags flags)
|
||||
{
|
||||
QVector<QCustomTypeInfo> *ct = customTypes();
|
||||
if (!ct || !typeName || !deleter || !creator)
|
||||
@ -470,6 +480,7 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
|
||||
inf.constructor = constructor;
|
||||
inf.destructor = destructor;
|
||||
inf.size = size;
|
||||
inf.flags = flags;
|
||||
idx = ct->size() + User;
|
||||
ct->append(inf);
|
||||
}
|
||||
@ -1633,6 +1644,73 @@ int QMetaType::sizeOf(int type)
|
||||
return QMetaTypeSwitcher::switcher<int>(sizeOf, type, 0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
class Flags
|
||||
{
|
||||
template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
|
||||
struct FlagsImpl
|
||||
{
|
||||
static quint32 Flags(const int)
|
||||
{
|
||||
return (!QTypeInfo<T>::isStatic * QMetaType::MovableType)
|
||||
| (QTypeInfo<T>::isComplex * QMetaType::NeedsConstruction)
|
||||
| (QTypeInfo<T>::isComplex * QMetaType::NeedsDestruction);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct FlagsImpl<T, /* IsAcceptedType = */ false>
|
||||
{
|
||||
static quint32 Flags(const int type)
|
||||
{
|
||||
return Flags::undefinedTypeFlags(type);
|
||||
}
|
||||
};
|
||||
public:
|
||||
Flags(const int type)
|
||||
: m_type(type)
|
||||
{}
|
||||
template<typename T>
|
||||
quint32 delegate(const T*) { return FlagsImpl<T>::Flags(m_type); }
|
||||
quint32 delegate(const QMetaTypeSwitcher::UnknownType*) { return customTypeFlags(m_type); }
|
||||
private:
|
||||
const int m_type;
|
||||
static quint32 customTypeFlags(const int type)
|
||||
{
|
||||
const QVector<QCustomTypeInfo> * const ct = customTypes();
|
||||
if (!ct)
|
||||
return 0;
|
||||
QReadLocker locker(customTypesLock());
|
||||
if (ct->count() <= type - QMetaType::User)
|
||||
return 0;
|
||||
return ct->at(type - QMetaType::User).flags;
|
||||
}
|
||||
static quint32 undefinedTypeFlags(const int type);
|
||||
};
|
||||
|
||||
quint32 Flags::undefinedTypeFlags(const int type)
|
||||
{
|
||||
if (type >= QMetaType::FirstGuiType && type <= QMetaType::LastGuiType)
|
||||
return qMetaTypeGuiHelper ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].flags : 0;
|
||||
else if (type >= QMetaType::FirstWidgetsType && type <= QMetaType::LastWidgetsType)
|
||||
return qMetaTypeWidgetsHelper ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].flags : 0;
|
||||
return customTypeFlags(type);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/*!
|
||||
\since 5.0
|
||||
|
||||
Returns flags of the given \a type.
|
||||
|
||||
\sa TypeFlags()
|
||||
*/
|
||||
QMetaType::TypeFlags QMetaType::typeFlags(int type)
|
||||
{
|
||||
Flags flags(type);
|
||||
return static_cast<QMetaType::TypeFlags>(QMetaTypeSwitcher::switcher<quint32>(flags, type, 0));
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int qRegisterMetaType(const char *typeName)
|
||||
\relates QMetaType
|
||||
|
@ -202,6 +202,13 @@ public:
|
||||
User = 256
|
||||
};
|
||||
|
||||
enum TypeFlag {
|
||||
NeedsConstruction = 0x1,
|
||||
NeedsDestruction = 0x2,
|
||||
MovableType = 0x4
|
||||
};
|
||||
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
|
||||
|
||||
typedef void (*Deleter)(void *);
|
||||
typedef void *(*Creator)(const void *);
|
||||
|
||||
@ -222,11 +229,13 @@ public:
|
||||
Creator creator,
|
||||
Destructor destructor,
|
||||
Constructor constructor,
|
||||
int size);
|
||||
int size,
|
||||
QMetaType::TypeFlags flags);
|
||||
static int registerTypedef(const char *typeName, int aliasId);
|
||||
static int type(const char *typeName);
|
||||
static const char *typeName(int type);
|
||||
static int sizeOf(int type);
|
||||
static TypeFlags typeFlags(int type);
|
||||
static bool isRegistered(int type);
|
||||
static void *create(int type, const void *copy = 0);
|
||||
#if QT_DEPRECATED_SINCE(5, 0)
|
||||
@ -246,6 +255,8 @@ public:
|
||||
|
||||
#undef QT_DEFINE_METATYPE_ID
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
|
||||
|
||||
template <typename T>
|
||||
void qMetaTypeDeleteHelper(T *t)
|
||||
{
|
||||
@ -334,11 +345,20 @@ int qRegisterMetaType(const char *typeName
|
||||
typedef void(*DestructPtr)(T*);
|
||||
DestructPtr ipdptr = qMetaTypeDestructHelper<T>;
|
||||
|
||||
QMetaType::TypeFlags flags;
|
||||
if (!QTypeInfo<T>::isStatic)
|
||||
flags |= QMetaType::MovableType;
|
||||
if (QTypeInfo<T>::isComplex) {
|
||||
flags |= QMetaType::NeedsConstruction;
|
||||
flags |= QMetaType::NeedsDestruction;
|
||||
}
|
||||
|
||||
return QMetaType::registerType(typeName, reinterpret_cast<QMetaType::Deleter>(dptr),
|
||||
reinterpret_cast<QMetaType::Creator>(cptr),
|
||||
reinterpret_cast<QMetaType::Destructor>(ipdptr),
|
||||
reinterpret_cast<QMetaType::Constructor>(ipcptr),
|
||||
sizeof(T));
|
||||
sizeof(T),
|
||||
flags);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
|
@ -150,6 +150,7 @@ public:
|
||||
QMetaType::Constructor constructor;
|
||||
QMetaType::Destructor destructor;
|
||||
int size;
|
||||
quint32 flags; // same as QMetaType::TypeFlags
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
@ -167,7 +168,10 @@ public:
|
||||
QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL(Type) \
|
||||
/*constructor*/(reinterpret_cast<QMetaType::Constructor>(QMetaTypeInterface::Impl<Type>::constructor)), \
|
||||
/*destructor*/(reinterpret_cast<QMetaType::Destructor>(QMetaTypeInterface::Impl<Type>::destructor)), \
|
||||
/*size*/(sizeof(Type)) \
|
||||
/*size*/(sizeof(Type)), \
|
||||
/*flags*/(!QTypeInfo<Type>::isStatic * QMetaType::MovableType) \
|
||||
| (QTypeInfo<Type>::isComplex * QMetaType::NeedsConstruction) \
|
||||
| (QTypeInfo<Type>::isComplex * QMetaType::NeedsDestruction) \
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -78,6 +78,8 @@ private slots:
|
||||
void createCopy();
|
||||
void sizeOf_data();
|
||||
void sizeOf();
|
||||
void flags_data();
|
||||
void flags();
|
||||
void construct_data();
|
||||
void construct();
|
||||
void constructCopy_data();
|
||||
@ -129,6 +131,10 @@ protected:
|
||||
#ifdef Q_OS_LINUX
|
||||
pthread_yield();
|
||||
#endif
|
||||
if (QMetaType::typeFlags(tp) != (QMetaType::NeedsConstruction | QMetaType::NeedsDestruction)) {
|
||||
++failureCount;
|
||||
qWarning() << "Wrong typeInfo returned for" << tp;
|
||||
}
|
||||
if (!QMetaType::isRegistered(tp)) {
|
||||
++failureCount;
|
||||
qWarning() << name << "is not a registered metatype";
|
||||
@ -578,6 +584,40 @@ void tst_QMetaType::sizeOf()
|
||||
QCOMPARE(QMetaType::sizeOf(type), size);
|
||||
}
|
||||
|
||||
struct CustomMovable {};
|
||||
QT_BEGIN_NAMESPACE
|
||||
Q_DECLARE_TYPEINFO(CustomMovable, Q_MOVABLE_TYPE);
|
||||
QT_END_NAMESPACE
|
||||
Q_DECLARE_METATYPE(CustomMovable);
|
||||
|
||||
void tst_QMetaType::flags_data()
|
||||
{
|
||||
QTest::addColumn<int>("type");
|
||||
QTest::addColumn<bool>("isMovable");
|
||||
QTest::addColumn<bool>("isComplex");
|
||||
|
||||
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
|
||||
QTest::newRow(#RealType) << MetaTypeId << bool(!QTypeInfo<RealType>::isStatic) << bool(QTypeInfo<RealType>::isComplex);
|
||||
QT_FOR_EACH_STATIC_CORE_CLASS(ADD_METATYPE_TEST_ROW)
|
||||
QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(ADD_METATYPE_TEST_ROW)
|
||||
QT_FOR_EACH_STATIC_CORE_POINTER(ADD_METATYPE_TEST_ROW)
|
||||
#undef ADD_METATYPE_TEST_ROW
|
||||
QTest::newRow("TestSpace::Foo") << ::qMetaTypeId<TestSpace::Foo>() << false << true;
|
||||
QTest::newRow("Whity<double>") << ::qMetaTypeId<Whity<double> >() << false << true;
|
||||
QTest::newRow("CustomMovable") << ::qMetaTypeId<CustomMovable>() << true << true;
|
||||
}
|
||||
|
||||
void tst_QMetaType::flags()
|
||||
{
|
||||
QFETCH(int, type);
|
||||
QFETCH(bool, isMovable);
|
||||
QFETCH(bool, isComplex);
|
||||
|
||||
QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::NeedsConstruction), isComplex);
|
||||
QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::NeedsDestruction), isComplex);
|
||||
QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::MovableType), isMovable);
|
||||
}
|
||||
|
||||
void tst_QMetaType::construct_data()
|
||||
{
|
||||
create_data();
|
||||
|
@ -56,6 +56,8 @@ private slots:
|
||||
void createCopy();
|
||||
void sizeOf_data();
|
||||
void sizeOf();
|
||||
void flags_data();
|
||||
void flags();
|
||||
void construct_data();
|
||||
void construct();
|
||||
void constructCopy_data();
|
||||
@ -320,6 +322,30 @@ struct TypeAlignment
|
||||
#endif
|
||||
};
|
||||
|
||||
void tst_QGuiMetaType::flags_data()
|
||||
{
|
||||
QTest::addColumn<int>("type");
|
||||
QTest::addColumn<bool>("isMovable");
|
||||
QTest::addColumn<bool>("isComplex");
|
||||
|
||||
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
|
||||
QTest::newRow(#RealType) << MetaTypeId << bool(!QTypeInfo<RealType>::isStatic) << bool(QTypeInfo<RealType>::isComplex);
|
||||
QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW)
|
||||
#undef ADD_METATYPE_TEST_ROW
|
||||
}
|
||||
|
||||
void tst_QGuiMetaType::flags()
|
||||
{
|
||||
QFETCH(int, type);
|
||||
QFETCH(bool, isMovable);
|
||||
QFETCH(bool, isComplex);
|
||||
|
||||
QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::NeedsConstruction), isComplex);
|
||||
QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::NeedsDestruction), isComplex);
|
||||
QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::MovableType), isMovable);
|
||||
}
|
||||
|
||||
|
||||
void tst_QGuiMetaType::construct_data()
|
||||
{
|
||||
create_data();
|
||||
|
Loading…
Reference in New Issue
Block a user