Optimize QObjectCompatProperty::notify
Do the check for inBindingWrapper() last. Change-Id: I3d589c9fba524f465e35cd4cc0e65e3af376b419 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
af2f88f5b6
commit
c6bc549b6b
@ -579,27 +579,33 @@ void QPropertyBindingData::notifyObservers(QUntypedPropertyData *propertyDataPtr
|
||||
QPropertyBindingDataPointer d{this};
|
||||
|
||||
if (QPropertyObserverPointer observer = d.firstObserver()) {
|
||||
auto status = storage ? storage->bindingStatus : nullptr;
|
||||
QPropertyDelayedNotifications *delay;
|
||||
#ifndef QT_HAS_FAST_CURRENT_THREAD_ID
|
||||
if (notifyObserver_helper(propertyDataPtr, observer, storage) == Evaluated) {
|
||||
// evaluateBindings() can trash the observers. We need to re-fetch here.
|
||||
if (QPropertyObserverPointer observer = d.firstObserver())
|
||||
observer.notify(propertyDataPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPropertyBindingData::NotificationResult QPropertyBindingData::notifyObserver_helper(
|
||||
QUntypedPropertyData *propertyDataPtr, QPropertyObserverPointer observer,
|
||||
QBindingStorage *storage) const
|
||||
{
|
||||
#ifdef QT_HAS_FAST_CURRENT_THREAD_ID
|
||||
QBindingStatus *status = storage ? storage->bindingStatus : nullptr;
|
||||
if (!status || status->threadId != QThread::currentThreadId())
|
||||
status = &bindingStatus;
|
||||
#else
|
||||
if (!status || status->threadId != QThread::currentThreadId())
|
||||
status = &bindingStatus;
|
||||
Q_UNUSED(storage);
|
||||
QBindingStatus *status = &bindingStatus;
|
||||
#endif
|
||||
delay = status->groupUpdateData;
|
||||
if (delay) {
|
||||
delay->addProperty(this, propertyDataPtr);
|
||||
return;
|
||||
}
|
||||
observer.evaluateBindings(status);
|
||||
} else {
|
||||
return;
|
||||
if (QPropertyDelayedNotifications *delay = status->groupUpdateData) {
|
||||
delay->addProperty(this, propertyDataPtr);
|
||||
return Delayed;
|
||||
}
|
||||
|
||||
// evaluateBindings() can trash the observers. We need to re-fetch here.
|
||||
if (QPropertyObserverPointer observer = d.firstObserver())
|
||||
observer.notify(propertyDataPtr);
|
||||
observer.evaluateBindings(status);
|
||||
return Evaluated;
|
||||
}
|
||||
|
||||
int QPropertyBindingDataPointer::observerCount() const
|
||||
|
@ -600,8 +600,22 @@ public:
|
||||
{
|
||||
QBindingStorage *storage = qGetBindingStorage(owner());
|
||||
if (auto bd = storage->bindingData(this, false)) {
|
||||
if (!inBindingWrapper(storage))
|
||||
notify(bd);
|
||||
// This partly duplicates QPropertyBindingData::notifyObservers because we want to
|
||||
// check for inBindingWrapper() after checking for isNotificationDelayed() and
|
||||
// firstObserver. This is because inBindingWrapper() is the most expensive check.
|
||||
if (!bd->isNotificationDelayed()) {
|
||||
QPropertyBindingDataPointer d{bd};
|
||||
if (QPropertyObserverPointer observer = d.firstObserver()) {
|
||||
if (!inBindingWrapper(storage)) {
|
||||
if (bd->notifyObserver_helper(this, observer, storage)
|
||||
== QtPrivate::QPropertyBindingData::Evaluated) {
|
||||
// evaluateBindings() can trash the observers. We need to re-fetch here.
|
||||
if (QPropertyObserverPointer observer = d.firstObserver())
|
||||
observer.notify(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if constexpr (!std::is_null_pointer_v<decltype(Signal)>) {
|
||||
if constexpr (SignalTakesValue::value)
|
||||
@ -649,13 +663,6 @@ public:
|
||||
auto *storage = const_cast<QBindingStorage *>(qGetBindingStorage(owner()));
|
||||
return *storage->bindingData(const_cast<QObjectCompatProperty *>(this), true);
|
||||
}
|
||||
|
||||
private:
|
||||
void notify(const QtPrivate::QPropertyBindingData *binding)
|
||||
{
|
||||
if (binding)
|
||||
binding->notifyObservers(this, qGetBindingStorage(owner()));
|
||||
}
|
||||
};
|
||||
|
||||
namespace QtPrivate {
|
||||
|
@ -151,6 +151,7 @@ private:
|
||||
class QUntypedPropertyBinding;
|
||||
class QPropertyBindingPrivate;
|
||||
struct QPropertyBindingDataPointer;
|
||||
struct QPropertyObserverPointer;
|
||||
|
||||
class QUntypedPropertyData
|
||||
{
|
||||
@ -334,6 +335,11 @@ private:
|
||||
quintptr d() const { return d_ref(); }
|
||||
void registerWithCurrentlyEvaluatingBinding_helper(BindingEvaluationState *currentBinding) const;
|
||||
void removeBinding_helper();
|
||||
|
||||
enum NotificationResult { Delayed, Evaluated };
|
||||
NotificationResult notifyObserver_helper(
|
||||
QUntypedPropertyData *propertyDataPtr, QPropertyObserverPointer observer,
|
||||
QBindingStorage *storage) const;
|
||||
};
|
||||
|
||||
template <typename T, typename Tag>
|
||||
|
Loading…
Reference in New Issue
Block a user