QProperty: optimize non-recursive notification logic

Previously, we were storing all binding-observers in a list, so that we
can later revisit them during the notification loop.
However, there is no point in doing that when the binding did not
actually change.

Pick-to: 6.4
Change-Id: I0b3343cc442eca2586c7c6a10c31d780f04730e6
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
bb10
Fabian Kosmale 2022-07-28 12:51:11 +02:00
parent 61806a058a
commit 3410b1dc9c
2 changed files with 10 additions and 8 deletions

View File

@ -276,7 +276,7 @@ void QPropertyBindingPrivate::unlinkAndDeref()
destroyAndFreeMemory(this);
}
void QPropertyBindingPrivate::evaluateRecursive(PendingBindingObserverList &bindingObservers, QBindingStatus *status)
bool QPropertyBindingPrivate::evaluateRecursive(PendingBindingObserverList &bindingObservers, QBindingStatus *status)
{
if (!status)
status = &bindingStatus;
@ -769,10 +769,11 @@ void QPropertyObserverPointer::evaluateBindings(PendingBindingObserverList &bind
QPropertyObserver *next = observer->next.data();
if (QPropertyObserver::ObserverTag(observer->next.tag()) == QPropertyObserver::ObserverNotifiesBinding) {
bindingObservers.push_back(observer);
auto bindingToEvaluate = observer->binding;
QPropertyObserverNodeProtector protector(observer);
bindingToEvaluate->evaluateRecursive_inline(bindingObservers, status);
QBindingObserverPtr bindingObserver(observer); // binding must not be gone after evaluateRecursive_inline
if (bindingToEvaluate->evaluateRecursive_inline(bindingObservers, status))
bindingObservers.push_back(std::move(bindingObserver));
next = protector.next();
}

View File

@ -360,7 +360,7 @@ public:
void unlinkAndDeref();
void evaluateRecursive(PendingBindingObserverList &bindingObservers, QBindingStatus *status = nullptr);
bool evaluateRecursive(PendingBindingObserverList &bindingObservers, QBindingStatus *status = nullptr);
// ### TODO: remove as soon as declarative no longer needs this overload
void evaluateRecursive()
@ -369,7 +369,7 @@ public:
evaluateRecursive(bindingObservers);
}
void Q_ALWAYS_INLINE evaluateRecursive_inline(PendingBindingObserverList &bindingObservers, QBindingStatus *status);
bool Q_ALWAYS_INLINE evaluateRecursive_inline(PendingBindingObserverList &bindingObservers, QBindingStatus *status);
void notifyRecursive();
void notifyNonRecursive(const PendingBindingObserverList &bindingObservers);
@ -780,13 +780,13 @@ struct QUntypedBindablePrivate
}
};
inline void QPropertyBindingPrivate::evaluateRecursive_inline(PendingBindingObserverList &bindingObservers, QBindingStatus *status)
inline bool QPropertyBindingPrivate::evaluateRecursive_inline(PendingBindingObserverList &bindingObservers, QBindingStatus *status)
{
if (updating) {
error = QPropertyBindingError(QPropertyBindingError::BindingLoop);
if (isQQmlPropertyBinding)
errorCallBack(this);
return;
return false;
}
/*
@ -816,10 +816,11 @@ inline void QPropertyBindingPrivate::evaluateRecursive_inline(PendingBindingObse
// If there was not, we must not clear it, as that only should happen in notifyRecursive
pendingNotify = pendingNotify || changed;
if (!changed || !firstObserver)
return;
return changed;
firstObserver.noSelfDependencies(this);
firstObserver.evaluateBindings(bindingObservers, status);
return true;
}
template<QPropertyObserverPointer::Notify notifyPolicy>