summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qproperty.h
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-07-08 12:07:13 +0200
committerLars Knoll <lars.knoll@qt.io>2020-07-10 15:07:12 +0200
commitbbfecdee1e2952c401e9c5ac6e16adc2428fb2dc (patch)
tree4b877d63b50606930bbac7416b3d164ae69cb70a /src/corelib/kernel/qproperty.h
parentbe1ce6b26909256e62c2b39e4de9f8f79d070937 (diff)
Significantly improve performance of binding evaluation
Avoid any QVariant or type dependent code in the cpp files. Instead, let the binding wrapper determine if the value has changed and return true/false accordingly. This required also some reworking of the guard mechanism for notified properties, where the guard function wrapper now calls first the binding evaluation function and then passes the result to the guard. Change-Id: I350d07a508ccc0c5db7054a0efa4f270b6a78ec3 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/corelib/kernel/qproperty.h')
-rw-r--r--src/corelib/kernel/qproperty.h33
1 files changed, 10 insertions, 23 deletions
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h
index 8a712d395e..5d26c1c0f4 100644
--- a/src/corelib/kernel/qproperty.h
+++ b/src/corelib/kernel/qproperty.h
@@ -120,7 +120,7 @@ class Q_CORE_EXPORT QUntypedPropertyBinding
{
public:
// writes binding result into dataPtr
- using BindingEvaluationFunction = std::function<void(const QMetaType &metaType, void *dataPtr)>;
+ using BindingEvaluationFunction = QtPrivate::QPropertyBindingFunction;
QUntypedPropertyBinding();
QUntypedPropertyBinding(const QMetaType &metaType, BindingEvaluationFunction function, const QPropertyBindingSourceLocation &location);
@@ -151,10 +151,14 @@ class QPropertyBinding : public QUntypedPropertyBinding
struct BindingAdaptor
{
Functor impl;
- void operator()(const QMetaType &/*metaType*/, void *dataPtr)
+ bool operator()(const QMetaType &/*metaType*/, void *dataPtr)
{
PropertyType *propertyPtr = static_cast<PropertyType *>(dataPtr);
- *propertyPtr = impl();
+ PropertyType newValue = impl();
+ if (newValue == *propertyPtr)
+ return false;
+ *propertyPtr = std::move(newValue);
+ return true;
}
};
@@ -352,20 +356,12 @@ namespace Qt {
}
}
-namespace detail {
- template <typename F>
- struct ExtractClassFromFunctionPointer;
-
- template<typename T, typename C>
- struct ExtractClassFromFunctionPointer<T C::*> { using Class = C; };
-}
-
template <typename T, auto Callback, auto ValueGuard=nullptr>
class QNotifiedProperty
{
public:
using value_type = T;
- using Class = typename detail::ExtractClassFromFunctionPointer<decltype(Callback)>::Class;
+ using Class = typename QtPrivate::detail::ExtractClassFromFunctionPointer<decltype(Callback)>::Class;
private:
static bool constexpr ValueGuardModifiesArgument = std::is_invocable_r_v<bool, decltype(ValueGuard), Class, T&>;
static bool constexpr CallbackAcceptsOldValue = std::is_invocable_v<decltype(Callback), Class, T>;
@@ -378,17 +374,8 @@ public:
!HasValueGuard,
"Guard has wrong signature");
private:
- // type erased guard functions, casts its arguments to the correct types
- static constexpr bool (*GuardTEHelper)(void *, void*) = [](void *o, void *newValue){
- if constexpr (HasValueGuard) { // Guard->* is invalid if Guard == nullptr
- return (reinterpret_cast<Class *>(o)->*(ValueGuard))(*static_cast<T *>(newValue));
- } else {
- Q_UNUSED(o); // some compilers complain about unused variables
- Q_UNUSED(newValue);
- return true;
- }
- };
- static constexpr bool(*GuardTE)(void *, void*) = HasValueGuard ? GuardTEHelper : nullptr;
+ static constexpr QtPrivate::QPropertyGuardFunction GuardTE =
+ QtPrivate::QPropertyGuardFunctionHelper<T, Class, ValueGuard>::guard;
public:
QNotifiedProperty() = default;