summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qmetatype.cpp
diff options
context:
space:
mode:
authorJędrzej Nowacki <jedrzej.nowacki@nokia.com>2011-12-20 17:11:46 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-16 02:00:15 +0100
commit214e031d56714ba69ef929f1e763e243b393e460 (patch)
tree4732bd79e015eecb85e66ba3a3facc58d5fba9ae /src/corelib/kernel/qmetatype.cpp
parentb9eb3715f55378802a1a0ae2f61d799ab84ee49a (diff)
Implement new static less API for QMetaType.
Currently QMetaType API contains almost only static methods. This works nice until someone needs more information or needs to do more operations on a type. In this case every function call has to do type dispatch. This API allows to avoid redundant type dispatching, by caching a type information in a QMetaType instance. It gives significant performance boost especially for custom types (up to 9x). Change-Id: I223d066268402e072e41ca1d0a3e7bc160655d7f Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com> Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
Diffstat (limited to 'src/corelib/kernel/qmetatype.cpp')
-rw-r--r--src/corelib/kernel/qmetatype.cpp170
1 files changed, 170 insertions, 0 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