diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2011-10-10 11:56:43 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-10-19 10:25:28 +0200 |
commit | 9e92ecde74d33eddd39de88472964fb20feaaebf (patch) | |
tree | c127c382451255cf64d6259c33dc34c754e965b8 /src/corelib/kernel/qmetatype.h | |
parent | ae30d71413595b3cb0550e047132ea07510d35a3 (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 'src/corelib/kernel/qmetatype.h')
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index e65c084ae0..660807c698 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -49,6 +49,8 @@ #include <QtCore/qdatastream.h> #endif +#include <new> + #ifdef Bool #error qmetatype.h must be included before any header file that defines Bool #endif @@ -106,6 +108,9 @@ public: typedef void (*Deleter)(void *); typedef void *(*Creator)(const void *); + 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 *); @@ -116,16 +121,20 @@ public: #endif static int registerType(const char *typeName, Deleter deleter, Creator creator); + static int registerType(const char *typeName, Deleter deleter, + Creator creator, + Destructor destructor, + Constructor constructor, + int size); 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 bool isRegistered(int type); static void *create(int type, const void *copy = 0); -#ifdef QT_DEPRECATED - QT_DEPRECATED static void *construct(int type, const void *copy = 0) - { return create(type, copy); } -#endif static void destroy(int type, void *data); + static void *construct(int type, void *where, const void *copy); + static void destruct(int type, void *where); static void unregisterType(const char *typeName); #ifndef QT_NO_DATASTREAM @@ -148,6 +157,21 @@ void *qMetaTypeCreateHelper(const T *t) return new T(*static_cast<const T*>(t)); } +template <typename T> +void qMetaTypeDestructHelper(T *t) +{ + t->~T(); +} + +template <typename T> +void *qMetaTypeConstructHelper(void *where, const T *t) +{ + if (!t) + return new (where) T; + else + return new (where) T(*static_cast<const T*>(t)); +} + #ifndef QT_NO_DATASTREAM template <typename T> void qMetaTypeSaveHelper(QDataStream &stream, const T *t) @@ -202,9 +226,16 @@ int qRegisterMetaType(const char *typeName CreatePtr cptr = qMetaTypeCreateHelper<T>; typedef void(*DeletePtr)(T*); DeletePtr dptr = qMetaTypeDeleteHelper<T>; + typedef void*(*ConstructPtr)(void *, const T*); + ConstructPtr ipcptr = qMetaTypeConstructHelper<T>; + typedef void(*DestructPtr)(T*); + DestructPtr ipdptr = qMetaTypeDestructHelper<T>; return QMetaType::registerType(typeName, reinterpret_cast<QMetaType::Deleter>(dptr), - reinterpret_cast<QMetaType::Creator>(cptr)); + reinterpret_cast<QMetaType::Creator>(cptr), + reinterpret_cast<QMetaType::Destructor>(ipdptr), + reinterpret_cast<QMetaType::Constructor>(ipcptr), + sizeof(T)); } #ifndef QT_NO_DATASTREAM |