summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qmetatype.cpp170
-rw-r--r--src/corelib/kernel/qmetatype.h145
-rw-r--r--src/corelib/kernel/qmetatype_p.h43
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp156
-rw-r--r--tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp54
5 files changed, 534 insertions, 34 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index d965c48255..a1baf28f10 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -1753,4 +1753,174 @@ QMetaType::TypeFlags QMetaType::typeFlags(int type)
\sa Q_DECLARE_METATYPE(), QMetaType::type()
*/
+namespace {
+class TypeInfo {
+ template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
+ struct TypeInfoImpl
+ {
+ TypeInfoImpl(const uint /* type */, QMetaTypeInterface &info)
+ {
+ QMetaTypeInterface tmp = QT_METATYPE_INTERFACE_INIT_NO_DATASTREAM(T);
+ info = tmp;
+ }
+ };
+
+ template<typename T>
+ struct TypeInfoImpl<T, /* IsAcceptedType = */ false>
+ {
+ TypeInfoImpl(const uint type, QMetaTypeInterface &info)
+ {
+ if (QTypeModuleInfo<T>::IsGui) {
+ if (Q_LIKELY(qMetaTypeGuiHelper))
+ info = qMetaTypeGuiHelper[type - QMetaType::FirstGuiType];
+ return;
+ }
+ if (QTypeModuleInfo<T>::IsWidget) {
+ if (Q_LIKELY(qMetaTypeWidgetsHelper))
+ info = qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType];
+ return;
+ }
+ }
+ };
+public:
+ QMetaTypeInterface info;
+ TypeInfo(const uint type)
+ : m_type(type)
+ {
+ QMetaTypeInterface tmp = QT_METATYPE_INTERFACE_INIT_EMPTY();
+ info = tmp;
+ }
+ template<typename T>
+ void delegate(const T*) { TypeInfoImpl<T>(m_type, info); }
+ void delegate(const void*) {}
+ void delegate(const QMetaTypeSwitcher::UnknownType*) { customTypeInfo(m_type); }
+private:
+ void customTypeInfo(const uint type)
+ {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ if (Q_UNLIKELY(!ct))
+ return;
+ QReadLocker locker(customTypesLock());
+ if (Q_LIKELY(uint(ct->count()) > type - QMetaType::User))
+ info = ct->at(type - QMetaType::User);
+ }
+
+ const uint m_type;
+};
+} // namespace
+
+QMetaType QMetaType::typeInfo(const int type)
+{
+ TypeInfo typeInfo(type);
+ QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
+ return typeInfo.info.creator || !type ? QMetaType(QMetaType::NoExtensionFlags
+ , static_cast<const QMetaTypeInterface *>(0) // typeInfo::info is a temporary variable, we can't return address of it.
+ , typeInfo.info.creator
+ , typeInfo.info.deleter
+ , typeInfo.info.saveOp
+ , typeInfo.info.loadOp
+ , typeInfo.info.constructor
+ , typeInfo.info.destructor
+ , typeInfo.info.size
+ , typeInfo.info.flags
+ , type)
+ : QMetaType(-1);
+}
+
+QMetaType::QMetaType(const int typeId)
+ : m_typeId(typeId)
+{
+ if (Q_UNLIKELY(typeId == -1)) {
+ // Constructs invalid QMetaType instance.
+ m_extensionFlags = 0xffffffff;
+ Q_ASSERT(!isValid());
+ } else {
+ // TODO it can be better.
+ *this = QMetaType::typeInfo(typeId);
+ if (m_typeId > 0 && !m_creator) {
+ m_extensionFlags = 0xffffffff;
+ m_typeId = -1;
+ }
+ if (m_typeId == QMetaType::Void) {
+ m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx;
+ }
+ }
+}
+
+QMetaType::QMetaType(const QMetaType &other)
+ : m_creator(other.m_creator)
+ , m_deleter(other.m_deleter)
+ , m_saveOp(other.m_saveOp)
+ , m_loadOp(other.m_loadOp)
+ , m_constructor(other.m_constructor)
+ , m_destructor(other.m_destructor)
+ , m_extension(other.m_extension) // space reserved for future use
+ , m_size(other.m_size)
+ , m_typeFlags(other.m_typeFlags)
+ , m_extensionFlags(other.m_extensionFlags)
+ , m_typeId(other.m_typeId)
+{}
+
+QMetaType &QMetaType::operator =(const QMetaType &other)
+{
+ m_creator = other.m_creator;
+ m_deleter = other.m_deleter;
+ m_saveOp = other.m_saveOp;
+ m_loadOp = other.m_loadOp;
+ m_constructor = other.m_constructor;
+ m_destructor = other.m_destructor;
+ m_size = other.m_size;
+ m_typeFlags = other.m_typeFlags;
+ m_extensionFlags = other.m_extensionFlags;
+ m_extension = other.m_extension; // space reserved for future use
+ m_typeId = other.m_typeId;
+ return *this;
+}
+
+void QMetaType::ctor(const QMetaTypeInterface *info)
+{
+ // Special case for Void type, the type is valid but not constructible.
+ // In future we may consider to remove this assert and extend this function to initialize
+ // differently m_extensionFlags for different types. Currently it is not needed.
+ Q_ASSERT(m_typeId == QMetaType::Void);
+ Q_UNUSED(info);
+ m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx;
+}
+
+void QMetaType::dtor()
+{}
+
+void *QMetaType::createExtended(const void *copy) const
+{
+ Q_UNUSED(copy);
+ return 0;
+}
+
+void QMetaType::destroyExtended(void *data) const
+{
+ Q_UNUSED(data);
+}
+
+void *QMetaType::constructExtended(void *where, const void *copy) const
+{
+ Q_UNUSED(where);
+ Q_UNUSED(copy);
+ return 0;
+}
+
+void QMetaType::destructExtended(void *data) const
+{
+ Q_UNUSED(data);
+}
+
+uint QMetaType::sizeExtended() const
+{
+ return 0;
+}
+
+QMetaType::TypeFlags QMetaType::flagsExtended() const
+{
+ return 0;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index ff3f9341e4..0b6a62e5c8 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -177,8 +177,16 @@ QT_BEGIN_NAMESPACE
TypeName = Id,
class QDataStream;
+class QMetaTypeInterface;
class Q_CORE_EXPORT QMetaType {
+ enum ExtensionFlag { NoExtensionFlags,
+ CreateEx = 0x1, DestroyEx = 0x2,
+ ConstructEx = 0x4, DestructEx = 0x8,
+ NameEx = 0x10, SizeEx = 0x20,
+ CtorEx = 0x40, DtorEx = 0x80,
+ FlagsEx = 0x100
+ };
public:
enum Type {
// these are merged with QVariant
@@ -218,9 +226,9 @@ public:
typedef void (*Destructor)(void *);
typedef void *(*Constructor)(void *, const void *);
-#ifndef QT_NO_DATASTREAM
typedef void (*SaveOperator)(QDataStream &, const void *);
typedef void (*LoadOperator)(QDataStream &, void *);
+#ifndef QT_NO_DATASTREAM
static void registerStreamOperators(const char *typeName, SaveOperator saveOp,
LoadOperator loadOp);
static void registerStreamOperators(int type, SaveOperator saveOp,
@@ -253,6 +261,56 @@ public:
static bool save(QDataStream &stream, int type, const void *data);
static bool load(QDataStream &stream, int type, void *data);
#endif
+
+ QMetaType(const int type);
+ inline ~QMetaType();
+
+ inline bool isValid() const;
+ inline bool isRegistered() const;
+ inline int sizeOf() const;
+ inline TypeFlags flags() const;
+
+ inline void *create(const void *copy = 0) const;
+ inline void destroy(void *data) const;
+ inline void *construct(void *where, const void *copy = 0) const;
+ inline void destruct(void *data) const;
+private:
+ static QMetaType typeInfo(const int type);
+ inline QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
+ Creator creator,
+ Deleter deleter,
+ SaveOperator saveOp,
+ LoadOperator loadOp,
+ Constructor constructor,
+ Destructor destructor,
+ uint sizeOf,
+ uint typeFlags,
+ int typeId);
+ QMetaType(const QMetaType &other);
+ QMetaType &operator =(const QMetaType &);
+ inline bool isExtended(const ExtensionFlag flag) const { return m_extensionFlags & flag; }
+
+ // Methods used for future binary compatibile extensions
+ void ctor(const QMetaTypeInterface *info);
+ void dtor();
+ uint sizeExtended() const;
+ QMetaType::TypeFlags flagsExtended() const;
+ void *createExtended(const void *copy = 0) const;
+ void destroyExtended(void *data) const;
+ void *constructExtended(void *where, const void *copy = 0) const;
+ void destructExtended(void *data) const;
+
+ Creator m_creator;
+ Deleter m_deleter;
+ SaveOperator m_saveOp;
+ LoadOperator m_loadOp;
+ Constructor m_constructor;
+ Destructor m_destructor;
+ void *m_extension; // space reserved for future use
+ uint m_size;
+ uint m_typeFlags;
+ uint m_extensionFlags;
+ int m_typeId;
};
#undef QT_DEFINE_METATYPE_ID
@@ -555,6 +613,91 @@ Q_DECLARE_METATYPE_TEMPLATE_1ARG(QSet)
Q_DECLARE_METATYPE_TEMPLATE_1ARG(QSharedPointer)
Q_DECLARE_METATYPE_TEMPLATE_1ARG(QLinkedList)
+inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
+ Creator creator,
+ Deleter deleter,
+ SaveOperator saveOp,
+ LoadOperator loadOp,
+ Constructor constructor,
+ Destructor destructor,
+ uint size,
+ uint typeFlags,
+ int typeId)
+ : m_creator(creator)
+ , m_deleter(deleter)
+ , m_saveOp(saveOp)
+ , m_loadOp(loadOp)
+ , m_constructor(constructor)
+ , m_destructor(destructor)
+ , m_size(size)
+ , m_typeFlags(typeFlags)
+ , m_extensionFlags(extensionFlags)
+ , m_typeId(typeId)
+{
+ if (Q_UNLIKELY(isExtended(CtorEx) || typeId == QMetaType::Void))
+ ctor(info);
+}
+
+inline QMetaType::~QMetaType()
+{
+ if (Q_UNLIKELY(isExtended(DtorEx)))
+ dtor();
+}
+
+inline bool QMetaType::isValid() const
+{
+ return m_typeId >= 0;
+}
+
+inline bool QMetaType::isRegistered() const
+{
+ return isValid();
+}
+
+inline void *QMetaType::create(const void *copy) const
+{
+ if (Q_UNLIKELY(isExtended(CreateEx)))
+ return createExtended(copy);
+ return m_creator(copy);
+}
+
+inline void QMetaType::destroy(void *data) const
+{
+ if (Q_UNLIKELY(isExtended(DestroyEx)))
+ return destroyExtended(data);
+ m_deleter(data);
+}
+
+inline void *QMetaType::construct(void *where, const void *copy) const
+{
+ if (Q_UNLIKELY(isExtended(ConstructEx)))
+ return constructExtended(where, copy);
+ return m_constructor(where, copy);
+}
+
+inline void QMetaType::destruct(void *data) const
+{
+ if (Q_UNLIKELY(isExtended(DestructEx)))
+ return destructExtended(data);
+ if (Q_UNLIKELY(!data))
+ return;
+ m_destructor(data);
+}
+
+inline int QMetaType::sizeOf() const
+{
+ if (Q_UNLIKELY(isExtended(SizeEx)))
+ return sizeExtended();
+ return m_size;
+}
+
+inline QMetaType::TypeFlags QMetaType::flags() const
+{
+ if (Q_UNLIKELY(isExtended(FlagsEx)))
+ return flagsExtended();
+ return QMetaType::TypeFlags(m_typeFlags);
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index b1edc350a1..e48c5d3033 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -132,10 +132,8 @@ public:
}
static void deleter(T *t) { delete t; }
- #ifndef QT_NO_DATASTREAM
static void saver(QDataStream &stream, const T *t) { stream << *t; }
static void loader(QDataStream &stream, T *t) { stream >> *t; }
- #endif // QT_NO_DATASTREAM
static void destructor(T *t)
{
Q_UNUSED(t) // Silence MSVC that warns for POD types.
@@ -151,10 +149,8 @@ public:
QMetaType::Creator creator;
QMetaType::Deleter deleter;
-#ifndef QT_NO_DATASTREAM
QMetaType::SaveOperator saveOp;
QMetaType::LoadOperator loadOp;
-#endif
QMetaType::Constructor constructor;
QMetaType::Destructor destructor;
int size;
@@ -165,10 +161,8 @@ template<>
struct QMetaTypeInterface::Impl<void> {
static void *creator(const void *) { return 0; }
static void deleter(void *) {}
-#ifndef QT_NO_DATASTREAM
static void saver(QDataStream &, const void *) {}
static void loader(QDataStream &, void *) {}
-#endif // QT_NO_DATASTREAM
static void destructor(void *){}
static void *constructor(void *, const void *) { return 0; }
};
@@ -177,15 +171,22 @@ struct QMetaTypeInterface::Impl<void> {
# define QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL(Type) \
/*saveOp*/(reinterpret_cast<QMetaType::SaveOperator>(QMetaTypeInterface::Impl<Type>::saver)), \
/*loadOp*/(reinterpret_cast<QMetaType::LoadOperator>(QMetaTypeInterface::Impl<Type>::loader)),
+# define QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type) \
+ /*saveOp*/ 0, \
+ /*loadOp*/ 0,
#else
-# define QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL(Type)
+# define QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type) \
+ /*saveOp*/ 0, \
+ /*loadOp*/ 0,
+# define QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL(Type) \
+ QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type)
#endif
-#define QT_METATYPE_INTERFACE_INIT(Type) \
+#define QT_METATYPE_INTERFACE_INIT_IMPL(Type, DATASTREAM_DELEGATE) \
{ \
/*creator*/(reinterpret_cast<QMetaType::Creator>(QMetaTypeInterface::Impl<Type>::creator)), \
/*deleter*/(reinterpret_cast<QMetaType::Deleter>(QMetaTypeInterface::Impl<Type>::deleter)), \
- QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL(Type) \
+ DATASTREAM_DELEGATE(Type) \
/*constructor*/(reinterpret_cast<QMetaType::Constructor>(QMetaTypeInterface::Impl<Type>::constructor)), \
/*destructor*/(reinterpret_cast<QMetaType::Destructor>(QMetaTypeInterface::Impl<Type>::destructor)), \
/*size*/(QTypeInfo<Type>::sizeOf), \
@@ -194,6 +195,30 @@ struct QMetaTypeInterface::Impl<void> {
| (QTypeInfo<Type>::isComplex * QMetaType::NeedsDestruction) \
}
+
+/* These QT_METATYPE_INTERFACE_INIT* macros are used to initialize QMetaTypeInterface instance.
+
+ - QT_METATYPE_INTERFACE_INIT(Type) -> It takes Type argument and creates all necessary wrapper functions for the Type,
+ it detects if QT_NO_DATASTREAM was defined. Probably it is the macro that you want to use.
+
+ - QT_METATYPE_INTERFACE_INIT_EMPTY() -> It initializes an empty QMetaTypeInterface instance.
+
+ - QT_METATYPE_INTERFACE_INIT_NO_DATASTREAM(Type) -> Temporary workaround for missing auto-detection of data stream
+ operators. It creates same instance as QT_METATYPE_INTERFACE_INIT(Type) but with null stream operators callbacks.
+ */
+#define QT_METATYPE_INTERFACE_INIT(Type) QT_METATYPE_INTERFACE_INIT_IMPL(Type, QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL)
+#define QT_METATYPE_INTERFACE_INIT_NO_DATASTREAM(Type) QT_METATYPE_INTERFACE_INIT_IMPL(Type, QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL)
+#define QT_METATYPE_INTERFACE_INIT_EMPTY() \
+{ \
+ /*creator*/ 0, \
+ /*deleter*/ 0, \
+ QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL() \
+ /*constructor*/ 0, \
+ /*destructor*/ 0, \
+ /*size*/ 0, \
+ /*flags*/ 0 \
+}
+
QT_END_NAMESPACE
#endif // QMETATYPE_P_H
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index f90e7f463f..72913d10f2 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -78,8 +78,12 @@ private slots:
void createCopy();
void sizeOf_data();
void sizeOf();
+ void sizeOfStaticLess_data();
+ void sizeOfStaticLess();
void flags_data();
void flags();
+ void flagsStaticLess_data();
+ void flagsStaticLess();
void construct_data();
void construct();
void constructCopy_data();
@@ -88,6 +92,8 @@ private slots:
void registerType();
void isRegistered_data();
void isRegistered();
+ void isRegisteredStaticLess_data();
+ void isRegisteredStaticLess();
void registerStreamBuiltin();
void automaticTemplateRegistration();
};
@@ -125,6 +131,9 @@ class MetaTypeTorturer: public QThread
protected:
void run()
{
+ Bar space[1];
+ space[0].~Bar();
+
for (int i = 0; i < 1000; ++i) {
const QByteArray name = QString("Bar%1_%2").arg(i).arg((size_t)QThread::currentThreadId()).toLatin1();
const char *nm = name.constData();
@@ -132,6 +141,15 @@ protected:
#ifdef Q_OS_LINUX
pthread_yield();
#endif
+ QMetaType info(tp);
+ if (!info.isValid()) {
+ ++failureCount;
+ qWarning() << "Wrong typeInfo returned for" << tp;
+ }
+ if (!info.isRegistered()) {
+ ++failureCount;
+ qWarning() << name << "is not a registered metatype";
+ }
if (QMetaType::typeFlags(tp) != (QMetaType::NeedsConstruction | QMetaType::NeedsDestruction)) {
++failureCount;
qWarning() << "Wrong typeInfo returned for" << tp;
@@ -148,9 +166,22 @@ protected:
++failureCount;
qWarning() << "Wrong typeName returned for" << tp;
}
- void *buf = QMetaType::create(tp, 0);
- void *buf2 = QMetaType::create(tp, buf);
- if (!buf) {
+ void *buf1 = QMetaType::create(tp, 0);
+ void *buf2 = QMetaType::create(tp, buf1);
+ void *buf3 = info.create(tp, 0);
+ void *buf4 = info.create(tp, buf1);
+
+ QMetaType::construct(tp, space, 0);
+ QMetaType::destruct(tp, space);
+ QMetaType::construct(tp, space, buf1);
+ QMetaType::destruct(tp, space);
+
+ info.construct(space, 0);
+ info.destruct(space);
+ info.construct(space, buf1);
+ info.destruct(space);
+
+ if (!buf1) {
++failureCount;
qWarning() << "Null buffer returned by QMetaType::create(tp, 0)";
}
@@ -158,9 +189,20 @@ protected:
++failureCount;
qWarning() << "Null buffer returned by QMetaType::create(tp, buf)";
}
- QMetaType::destroy(tp, buf);
+ if (!buf3) {
+ ++failureCount;
+ qWarning() << "Null buffer returned by info.create(tp, 0)";
+ }
+ if (!buf4) {
+ ++failureCount;
+ qWarning() << "Null buffer returned by infocreate(tp, buf)";
+ }
+ QMetaType::destroy(tp, buf1);
QMetaType::destroy(tp, buf2);
+ info.destroy(buf3);
+ info.destroy(buf4);
}
+ new (space) Bar;
}
public:
MetaTypeTorturer() : failureCount(0) { }
@@ -480,13 +522,17 @@ template<int ID>
static void testCreateHelper()
{
typedef typename MetaEnumToType<ID>::Type Type;
- void *actual = QMetaType::create(ID);
+ QMetaType info(ID);
+ void *actual1 = QMetaType::create(ID);
+ void *actual2 = info.create();
if (DefaultValueTraits<ID>::IsInitialized) {
Type *expected = DefaultValueFactory<ID>::create();
- QCOMPARE(*static_cast<Type *>(actual), *expected);
+ QCOMPARE(*static_cast<Type *>(actual1), *expected);
+ QCOMPARE(*static_cast<Type *>(actual2), *expected);
delete expected;
}
- QMetaType::destroy(ID, actual);
+ QMetaType::destroy(ID, actual1);
+ info.destroy(actual2);
}
template<>
@@ -529,9 +575,13 @@ static void testCreateCopyHelper()
{
typedef typename MetaEnumToType<ID>::Type Type;
Type *expected = TestValueFactory<ID>::create();
- void *actual = QMetaType::create(ID, expected);
- QCOMPARE(*static_cast<Type *>(actual), *expected);
- QMetaType::destroy(ID, actual);
+ QMetaType info(ID);
+ void *actual1 = QMetaType::create(ID, expected);
+ void *actual2 = info.create(expected);
+ QCOMPARE(*static_cast<Type *>(actual1), *expected);
+ QCOMPARE(*static_cast<Type *>(actual2), *expected);
+ QMetaType::destroy(ID, actual1);
+ info.destroy(actual2);
delete expected;
}
@@ -588,6 +638,18 @@ void tst_QMetaType::sizeOf()
QCOMPARE(QMetaType::sizeOf(type), size);
}
+void tst_QMetaType::sizeOfStaticLess_data()
+{
+ sizeOf_data();
+}
+
+void tst_QMetaType::sizeOfStaticLess()
+{
+ QFETCH(QMetaType::Type, type);
+ QFETCH(int, size);
+ QCOMPARE(QMetaType(type).sizeOf(), size);
+}
+
struct CustomMovable {};
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(CustomMovable, Q_MOVABLE_TYPE);
@@ -653,6 +715,23 @@ void tst_QMetaType::flags()
QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::PointerToQObject), isPointerToQObject);
}
+void tst_QMetaType::flagsStaticLess_data()
+{
+ flags_data();
+}
+
+void tst_QMetaType::flagsStaticLess()
+{
+ QFETCH(int, type);
+ QFETCH(bool, isMovable);
+ QFETCH(bool, isComplex);
+
+ int flags = QMetaType(type).flags();
+ QCOMPARE(bool(flags & QMetaType::NeedsConstruction), isComplex);
+ QCOMPARE(bool(flags & QMetaType::NeedsDestruction), isComplex);
+ QCOMPARE(bool(flags & QMetaType::MovableType), isMovable);
+}
+
void tst_QMetaType::construct_data()
{
create_data();
@@ -688,20 +767,30 @@ template<int ID>
static void testConstructHelper()
{
typedef typename MetaEnumToType<ID>::Type Type;
- int size = QMetaType::sizeOf(ID);
- void *storage = qMallocAligned(size, TypeAlignment<Type>::Value);
- void *actual = QMetaType::construct(ID, storage, /*copy=*/0);
- QCOMPARE(actual, storage);
+ QMetaType info(ID);
+ int size = info.sizeOf();
+ void *storage1 = qMallocAligned(size, TypeAlignment<Type>::Value);
+ void *actual1 = QMetaType::construct(ID, storage1, /*copy=*/0);
+ void *storage2 = qMallocAligned(size, TypeAlignment<Type>::Value);
+ void *actual2 = info.construct(storage2, /*copy=*/0);
+ QCOMPARE(actual1, storage1);
+ QCOMPARE(actual2, storage2);
if (DefaultValueTraits<ID>::IsInitialized) {
Type *expected = DefaultValueFactory<ID>::create();
- QCOMPARE(*static_cast<Type *>(actual), *expected);
+ QCOMPARE(*static_cast<Type *>(actual1), *expected);
+ QCOMPARE(*static_cast<Type *>(actual2), *expected);
delete expected;
}
- QMetaType::destruct(ID, actual);
- qFreeAligned(storage);
+ QMetaType::destruct(ID, actual1);
+ qFreeAligned(storage1);
+ info.destruct(actual2);
+ qFreeAligned(storage2);
QVERIFY(QMetaType::construct(ID, 0, /*copy=*/0) == 0);
QMetaType::destruct(ID, 0);
+
+ QVERIFY(info.construct(0, /*copy=*/0) == 0);
+ info.destruct(0);
}
template<>
@@ -748,15 +837,24 @@ static void testConstructCopyHelper()
{
typedef typename MetaEnumToType<ID>::Type Type;
Type *expected = TestValueFactory<ID>::create();
+ QMetaType info(ID);
int size = QMetaType::sizeOf(ID);
- void *storage = qMallocAligned(size, TypeAlignment<Type>::Value);
- void *actual = QMetaType::construct(ID, storage, expected);
- QCOMPARE(actual, storage);
- QCOMPARE(*static_cast<Type *>(actual), *expected);
- QMetaType::destruct(ID, actual);
- qFreeAligned(storage);
+ QCOMPARE(info.sizeOf(), size);
+ void *storage1 = qMallocAligned(size, TypeAlignment<Type>::Value);
+ void *actual1 = QMetaType::construct(ID, storage1, expected);
+ void *storage2 = qMallocAligned(size, TypeAlignment<Type>::Value);
+ void *actual2 = info.construct(storage2, expected);
+ QCOMPARE(actual1, storage1);
+ QCOMPARE(actual2, storage2);
+ QCOMPARE(*static_cast<Type *>(actual1), *expected);
+ QCOMPARE(*static_cast<Type *>(actual2), *expected);
+ QMetaType::destruct(ID, actual1);
+ qFreeAligned(storage1);
+ info.destruct(actual2);
+ qFreeAligned(storage2);
QVERIFY(QMetaType::construct(ID, 0, expected) == 0);
+ QVERIFY(info.construct(0, expected) == 0);
delete expected;
}
@@ -895,6 +993,18 @@ void tst_QMetaType::isRegistered()
QCOMPARE(QMetaType::isRegistered(typeId), registered);
}
+void tst_QMetaType::isRegisteredStaticLess_data()
+{
+ isRegistered_data();
+}
+
+void tst_QMetaType::isRegisteredStaticLess()
+{
+ QFETCH(int, typeId);
+ QFETCH(bool, registered);
+ QCOMPARE(QMetaType(typeId).isRegistered(), registered);
+}
+
void tst_QMetaType::registerStreamBuiltin()
{
//should not crash;
diff --git a/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp
index 1c5dc9227f..a3cdd38e56 100644
--- a/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -72,6 +72,8 @@ private slots:
void constructCoreType_data();
void constructCoreType();
+ void constructCoreTypeStaticLess_data();
+ void constructCoreTypeStaticLess();
void constructCoreTypeCopy_data();
void constructCoreTypeCopy();
@@ -79,6 +81,8 @@ private slots:
void constructInPlace();
void constructInPlaceCopy_data();
void constructInPlaceCopy();
+ void constructInPlaceCopyStaticLess_data();
+ void constructInPlaceCopyStaticLess();
};
tst_QMetaType::tst_QMetaType()
@@ -89,6 +93,12 @@ tst_QMetaType::~tst_QMetaType()
{
}
+struct BigClass
+{
+ double n,i,e,r,o,b;
+};
+Q_DECLARE_METATYPE(BigClass);
+
void tst_QMetaType::typeBuiltin_data()
{
QTest::addColumn<QByteArray>("typeName");
@@ -260,6 +270,23 @@ void tst_QMetaType::constructCoreType()
}
}
+void tst_QMetaType::constructCoreTypeStaticLess_data()
+{
+ constructCoreType_data();
+}
+
+void tst_QMetaType::constructCoreTypeStaticLess()
+{
+ QFETCH(int, typeId);
+ QBENCHMARK {
+ QMetaType type(typeId);
+ for (int i = 0; i < 100000; ++i) {
+ void *data = type.create((void *)0);
+ type.destroy(data);
+ }
+ }
+}
+
void tst_QMetaType::constructCoreTypeCopy_data()
{
constructCoreType_data();
@@ -285,6 +312,7 @@ void tst_QMetaType::constructCoreTypeCopy()
void tst_QMetaType::constructInPlace_data()
{
constructCoreType_data();
+ QTest::newRow("custom") << qMetaTypeId<BigClass>();
}
void tst_QMetaType::constructInPlace()
@@ -305,7 +333,7 @@ void tst_QMetaType::constructInPlace()
void tst_QMetaType::constructInPlaceCopy_data()
{
- constructCoreType_data();
+ constructInPlace_data();
}
void tst_QMetaType::constructInPlaceCopy()
@@ -326,5 +354,29 @@ void tst_QMetaType::constructInPlaceCopy()
qFreeAligned(storage);
}
+void tst_QMetaType::constructInPlaceCopyStaticLess_data()
+{
+ constructInPlaceCopy_data();
+}
+
+void tst_QMetaType::constructInPlaceCopyStaticLess()
+{
+ QFETCH(int, typeId);
+ int size = QMetaType::sizeOf(typeId);
+ void *storage = qMallocAligned(size, 2 * sizeof(qlonglong));
+ void *other = QMetaType::create(typeId);
+ QCOMPARE(QMetaType::construct(typeId, storage, other), storage);
+ QMetaType::destruct(typeId, storage);
+ QBENCHMARK {
+ QMetaType type(typeId);
+ for (int i = 0; i < 100000; ++i) {
+ type.construct(storage, other);
+ type.destruct(storage);
+ }
+ }
+ QMetaType::destroy(typeId, other);
+ qFreeAligned(storage);
+}
+
QTEST_MAIN(tst_QMetaType)
#include "tst_qmetatype.moc"