diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-06-28 15:27:43 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-08-08 21:59:46 +0200 |
commit | 226d0981cdf1da8ca8ee53d88b663eea14de41e5 (patch) | |
tree | e462ece91179629e9122f647249814a8b7632008 /src/corelib/kernel/qproperty.cpp | |
parent | 63e1cf916d5f8783634ac3c10c5be114d3711df5 (diff) |
QProperty: more micro optimization
- Provide an inline version of evaluateRecursive which does not fetch the
status.
- Provide an unsafe variant of setBindingToNotify which does not set the
tag. This can be used in allocateDependencyObserver, as newly
allocated observers already have the correct tag (this is checked via
an assert).
Change-Id: I31aec6af4aef244efc6d0777e5bfaaa8f82f2046
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
(cherry picked from commit f7eed15588fc93af417b8969fe4e498936d81e04)
Diffstat (limited to 'src/corelib/kernel/qproperty.cpp')
-rw-r--r-- | src/corelib/kernel/qproperty.cpp | 54 |
1 files changed, 14 insertions, 40 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 97854f8ac3..0055e6a5ff 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -285,44 +285,7 @@ void QPropertyBindingPrivate::unlinkAndDeref() void QPropertyBindingPrivate::evaluateRecursive(QBindingStatus *status) { - if (updating) { - error = QPropertyBindingError(QPropertyBindingError::BindingLoop); - if (isQQmlPropertyBinding) - errorCallBack(this); - return; - } - - QScopedValueRollback<bool> updateGuard(updating, true); - - /* - * Evaluating the binding might lead to the binding being broken. This can - * cause ref to reach zero at the end of the function. However, the - * updateGuard's destructor will then still trigger, trying to set the - * updating bool to its old value - * To prevent this, we create a QPropertyBindingPrivatePtr which ensures - * that the object is still alive when updateGuard's dtor runs. - */ - QPropertyBindingPrivatePtr keepAlive {this}; - - BindingEvaluationState evaluationFrame(this, status); - - auto bindingFunctor = reinterpret_cast<std::byte *>(this) + - QPropertyBindingPrivate::getSizeEnsuringAlignment(); - bool changed = false; - if (hasBindingWrapper) { - changed = staticBindingWrapper(metaType, propertyDataPtr, - {vtable, bindingFunctor}); - } else { - changed = vtable->call(metaType, propertyDataPtr, bindingFunctor); - } - // If there was a change, we must set pendingNotify. - // If there was not, we must not clear it, as that only should happen in notifyRecursive - pendingNotify = pendingNotify || changed; - if (!changed || !firstObserver) - return; - - firstObserver.noSelfDependencies(this); - firstObserver.evaluateBindings(status); + return evaluateRecursive_inline(status); } void QPropertyBindingPrivate::notifyRecursive() @@ -539,7 +502,8 @@ void QPropertyBindingData::registerWithCurrentlyEvaluatingBinding_helper(Binding QPropertyBindingDataPointer d{this}; QPropertyObserverPointer dependencyObserver = currentState->binding->allocateDependencyObserver(); - dependencyObserver.setBindingToNotify(currentState->binding); + Q_ASSERT(QPropertyObserver::ObserverNotifiesBinding == 0); + dependencyObserver.setBindingToNotify_unsafe(currentState->binding); d.addObserver(dependencyObserver.ptr); } @@ -664,6 +628,16 @@ void QPropertyObserverPointer::setBindingToNotify(QPropertyBindingPrivate *bindi } /*! + \internal + The same as as setBindingToNotify, but assumes that the tag is already correct. + */ +void QPropertyObserverPointer::setBindingToNotify_unsafe(QPropertyBindingPrivate *binding) +{ + Q_ASSERT(ptr->next.tag() == QPropertyObserver::ObserverNotifiesBinding); + ptr->binding = binding; +} + +/*! \internal QPropertyObserverNodeProtector is a RAII wrapper which takes care of the internal switching logic for QPropertyObserverPointer::notify (described ibidem) @@ -775,7 +749,7 @@ void QPropertyObserverPointer::evaluateBindings(QBindingStatus *status) if (QPropertyObserver::ObserverTag(observer->next.tag()) == QPropertyObserver::ObserverNotifiesBinding) { auto bindingToEvaluate = observer->binding; QPropertyObserverNodeProtector protector(observer); - bindingToEvaluate->evaluateRecursive(status); + bindingToEvaluate->evaluateRecursive_inline(status); next = protector.next(); } |