summaryrefslogtreecommitdiffstats
path: root/tests/auto/gui/kernel/qguimetatype
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2011-10-10 11:56:43 +0200
committerQt by Nokia <qt-info@nokia.com>2011-10-19 10:25:28 +0200
commit9e92ecde74d33eddd39de88472964fb20feaaebf (patch)
treec127c382451255cf64d6259c33dc34c754e965b8 /tests/auto/gui/kernel/qguimetatype
parentae30d71413595b3cb0550e047132ea07510d35a3 (diff)
Provide API for "placement new" construction of meta-types
By making it possible to specify the place in memory where a type should be constructed, any meta-type can be allocated on the stack, for example. In the QML/JS QObject binding, this makes it possible to call slots and access properties from JavaScript without having to perform any mallocs (e.g. due to QVariant creation) in the C++ <--> JS value conversion, in the best case. In addition to QMetaType::construct() and QMetaType::destruct(), this change introduces QMetaType::typeSize(), which returns the size of a type in bytes. This can be used to prepare a suitable buffer for constructing a type using construct(). Benchmarks indicate that in-place construction is 2-5x faster than normal construction for core and GUI types on linux-g++. Note that there is already a QMetaType::construct() function in Qt 4, which has been renamed to QMetaType::create() in Qt 5. In order to avoid existing usages of construct() in user code to call the Qt 5 construct() (when they really meant to call create()), the third argument ("copy") of construct() is made mandatory. Hence, calls to QMetaType::construct() written for Qt 4 will cause a compile error when compiled with Qt 5, and the user must adapt his code. Task-number: QTBUG-12574 Change-Id: I836f06f6ee1c1c3edbd199a03424c78c942bdd3e Reviewed-by: João Abecasis <joao.abecasis@nokia.com> Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Diffstat (limited to 'tests/auto/gui/kernel/qguimetatype')
-rw-r--r--tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
index 4b5aa347a8..98314a9336 100644
--- a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
+++ b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
@@ -54,6 +54,12 @@ private slots:
void create();
void createCopy_data();
void createCopy();
+ void sizeOf_data();
+ void sizeOf();
+ void construct_data();
+ void construct();
+ void constructCopy_data();
+ void constructCopy();
};
#define FOR_EACH_GUI_METATYPE(F) \
@@ -271,5 +277,130 @@ FOR_EACH_GUI_METATYPE(RETURN_CREATE_COPY_FUNCTION)
TypeTestFunctionGetter::get(type)();
}
+void tst_QGuiMetaType::sizeOf_data()
+{
+ QTest::addColumn<QMetaType::Type>("type");
+ QTest::addColumn<int>("size");
+#define ADD_METATYPE_TEST_ROW(TYPE, ID) \
+ QTest::newRow(QMetaType::typeName(QMetaType::ID)) << QMetaType::ID << int(sizeof(TYPE));
+FOR_EACH_GUI_METATYPE(ADD_METATYPE_TEST_ROW)
+#undef ADD_METATYPE_TEST_ROW
+}
+
+void tst_QGuiMetaType::sizeOf()
+{
+ QFETCH(QMetaType::Type, type);
+ QFETCH(int, size);
+ QCOMPARE(QMetaType::sizeOf(type), size);
+}
+
+#ifndef Q_ALIGNOF
+template<uint N>
+struct RoundToNextHighestPowerOfTwo
+{
+private:
+ enum { V1 = N-1 };
+ enum { V2 = V1 | (V1 >> 1) };
+ enum { V3 = V2 | (V2 >> 2) };
+ enum { V4 = V3 | (V3 >> 4) };
+ enum { V5 = V4 | (V4 >> 8) };
+ enum { V6 = V5 | (V5 >> 16) };
+public:
+ enum { Value = V6 + 1 };
+};
+#endif
+
+template<class T>
+struct TypeAlignment
+{
+#ifdef Q_ALIGNOF
+ enum { Value = Q_ALIGNOF(T) };
+#else
+ enum { Value = RoundToNextHighestPowerOfTwo<sizeof(T)>::Value };
+#endif
+};
+
+void tst_QGuiMetaType::construct_data()
+{
+ create_data();
+}
+
+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);
+ Type *expected = DefaultValueFactory<ID>::create();
+ QVERIFY2(TypeComparator<ID>::equal(*static_cast<Type *>(actual), *expected), QMetaType::typeName(ID));
+ delete expected;
+ QMetaType::destruct(ID, actual);
+ qFreeAligned(storage);
+}
+
+void tst_QGuiMetaType::construct()
+{
+ struct TypeTestFunctionGetter
+ {
+ static TypeTestFunction get(int type)
+ {
+ switch (type) {
+#define RETURN_CONSTRUCT_FUNCTION(TYPE, ID) \
+ case QMetaType::ID: \
+ return testConstructHelper<QMetaType::ID>;
+FOR_EACH_GUI_METATYPE(RETURN_CONSTRUCT_FUNCTION)
+#undef RETURN_CONSTRUCT_FUNCTION
+ }
+ return 0;
+ }
+ };
+
+ QFETCH(QMetaType::Type, type);
+ TypeTestFunctionGetter::get(type)();
+}
+
+void tst_QGuiMetaType::constructCopy_data()
+{
+ create_data();
+}
+
+template <int ID>
+static void testConstructCopyHelper()
+{
+ typedef typename MetaEnumToType<ID>::Type Type;
+ Type *expected = TestValueFactory<ID>::create();
+ int size = QMetaType::sizeOf(ID);
+ void *storage = qMallocAligned(size, TypeAlignment<Type>::Value);
+ void *actual = QMetaType::construct(ID, storage, expected);
+ QCOMPARE(actual, storage);
+ QVERIFY2(TypeComparator<ID>::equal(*static_cast<Type*>(actual), *expected), QMetaType::typeName(ID));
+ QMetaType::destruct(ID, actual);
+ qFreeAligned(storage);
+ delete expected;
+}
+
+void tst_QGuiMetaType::constructCopy()
+{
+ struct TypeTestFunctionGetter
+ {
+ static TypeTestFunction get(int type)
+ {
+ switch (type) {
+#define RETURN_CONSTRUCT_COPY_FUNCTION(TYPE, ID) \
+ case QMetaType::ID: \
+ return testConstructCopyHelper<QMetaType::ID>;
+FOR_EACH_GUI_METATYPE(RETURN_CONSTRUCT_COPY_FUNCTION)
+#undef RETURN_CONSTRUCT_COPY_FUNCTION
+ }
+ return 0;
+ }
+ };
+
+ QFETCH(QMetaType::Type, type);
+ TypeTestFunctionGetter::get(type)();
+}
+
QTEST_MAIN(tst_QGuiMetaType)
#include "tst_qguimetatype.moc"