summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qmetatype.h
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2021-08-02 15:01:40 +0200
committerMarc Mutz <marc.mutz@kdab.com>2021-08-04 13:32:40 +0200
commitfa7f4c5efd91c852341dd2e56396ee3f5fedd33a (patch)
treef0dfe0af5b2d0e5dc1b643e648511916147dcded /src/corelib/kernel/qmetatype.h
parente933d71a610a951cc6af3c2ac40b97037a14bf9c (diff)
QMetaType: auto-unregister converters and mutable views again
The port from hand-rolled function storage to std::function inadvertently removed the helper variable of static storage duration whose dtor would unregister the conversion function. This caused QTBUG-94831, where the cleanup of conversion functions attempts to call code (via std::function) from a library that has already been unloaded. Restore the 5.15 behavior by adding a static-storage-duration scope guard to unregister the conversion and view functions from Qt upon library unload (when static objects are destroyed). Unlike 5.15, only install the scope guard upon successful registration, ensuring that only the DLL which successfully registered its conversion function unregisters it again. Amends 0e4ae4fbf8e320d18c29a55b5db2bba25b3d9d50. Add some strategic std::move()s as a drive-by. Pick-to: 6.2 Task-number: QTBUG-94831 Change-Id: I391ca667420cf0d98a166676b9bb363d6e190306 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel/qmetatype.h')
-rw-r--r--src/corelib/kernel/qmetatype.h45
1 files changed, 37 insertions, 8 deletions
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index adc4ae92d5..6611e34c33 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -48,6 +48,7 @@
#include <QtCore/qcompare.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qrefcount.h>
+#include <QtCore/qscopeguard.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qiterable.h>
#ifndef QT_NO_QOBJECT
@@ -570,7 +571,7 @@ public:
*t = (f->*function)();
return true;
};
- return registerConverterFunction(converter, fromType, toType);
+ return registerConverterImpl<From, To>(converter, fromType, toType);
}
// member function
@@ -588,7 +589,7 @@ public:
*t = (f->*function)();
return true;
};
- return registerMutableViewFunction(view, fromType, toType);
+ return registerMutableViewImpl<From, To>(view, fromType, toType);
}
// member function as in "double QString::toDouble(bool *ok = nullptr) const"
@@ -609,7 +610,7 @@ public:
*t = To();
return result;
};
- return registerConverterFunction(converter, fromType, toType);
+ return registerConverterImpl<From, To>(converter, fromType, toType);
}
// functor or function pointer
@@ -621,13 +622,13 @@ public:
const QMetaType fromType = QMetaType::fromType<From>();
const QMetaType toType = QMetaType::fromType<To>();
- auto converter = [function](const void *from, void *to) -> bool {
+ auto converter = [function = std::move(function)](const void *from, void *to) -> bool {
const From *f = static_cast<const From *>(from);
To *t = static_cast<To *>(to);
*t = function(*f);
return true;
};
- return registerConverterFunction(converter, fromType, toType);
+ return registerConverterImpl<From, To>(std::move(converter), fromType, toType);
}
// functor or function pointer
@@ -639,15 +640,43 @@ public:
const QMetaType fromType = QMetaType::fromType<From>();
const QMetaType toType = QMetaType::fromType<To>();
- auto view = [function](void *from, void *to) -> bool {
+ auto view = [function = std::move(function)](void *from, void *to) -> bool {
From *f = static_cast<From *>(from);
To *t = static_cast<To *>(to);
*t = function(*f);
return true;
};
- return registerMutableViewFunction(view, fromType, toType);
+ return registerMutableViewImpl<From, To>(std::move(view), fromType, toType);
}
-#endif
+
+private:
+ template<typename From, typename To>
+ static bool registerConverterImpl(ConverterFunction converter, QMetaType fromType, QMetaType toType)
+ {
+ if (registerConverterFunction(std::move(converter), fromType, toType)) {
+ static const auto unregister = qScopeGuard([=] {
+ unregisterConverterFunction(fromType, toType);
+ });
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ template<typename From, typename To>
+ static bool registerMutableViewImpl(MutableViewFunction view, QMetaType fromType, QMetaType toType)
+ {
+ if (registerMutableViewFunction(std::move(view), fromType, toType)) {
+ static const auto unregister = qScopeGuard([=] {
+ unregisterMutableViewFunction(fromType, toType);
+ });
+ return true;
+ } else {
+ return false;
+ }
+ }
+#endif // Q_CLANG_DOC
+public:
static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to);
static bool canConvert(QMetaType fromType, QMetaType toType);