summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qproperty.cpp
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-08-18 14:10:12 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-08-23 14:46:22 +0000
commit7f97d21105f0164c1d3d623d66af56b9f52ae19b (patch)
tree4a34aa798f33e8dd7d703cc9927029032e7b6575 /src/corelib/kernel/qproperty.cpp
parent469ab6fb956e26771da0cbe2850a72983c206d74 (diff)
Re-add QPropertyAlias functionality
As QPropertyAlias was public by accident in 6.0, we have to ensure that it still works in 6.2. This re-adds some tests for it, and reimplements the unlinking functionality. To avoid performance regressions in hot-paths, a new unlink_fast function is added, which behaves like the old unlink: It ignores the special handling for QPropertyAlias, so that we can skip the tag check. It is only used in QPropertyObserverNodeProtector and clearDependencyObservers, where we already know the type of the observer. Fixes: QTBUG-95846 Change-Id: Ifb405b8327c4d61c673b1a912ed6e169d27c2d8f Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> (cherry picked from commit e4d62651c278c468f71ce097979bc1183ffd0713) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/corelib/kernel/qproperty.cpp')
-rw-r--r--src/corelib/kernel/qproperty.cpp43
1 files changed, 34 insertions, 9 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp
index 3123858d83..942abfe6ba 100644
--- a/src/corelib/kernel/qproperty.cpp
+++ b/src/corelib/kernel/qproperty.cpp
@@ -558,9 +558,10 @@ QPropertyObserver::QPropertyObserver(ChangeHandler changeHandler)
d.setChangeHandler(changeHandler);
}
-QPropertyObserver::QPropertyObserver(QUntypedPropertyData *)
+QPropertyObserver::QPropertyObserver(QUntypedPropertyData *data)
{
- // ### Qt 7: Remove, currently left for binary compatibility
+ aliasData = data;
+ next.setTag(ObserverIsAlias);
}
/*! \internal
@@ -609,16 +610,38 @@ QPropertyObserver &QPropertyObserver::operator=(QPropertyObserver &&other) noexc
return *this;
}
+#define UNLINK_COMMON \
+ if (ptr->next) \
+ ptr->next->prev = ptr->prev; \
+ if (ptr->prev) \
+ ptr->prev.setPointer(ptr->next.data()); \
+ ptr->next = nullptr; \
+ ptr->prev.clear();
+
+/*!
+ \internal
+ Unlinks
+ */
void QPropertyObserverPointer::unlink()
{
- if (ptr->next)
- ptr->next->prev = ptr->prev;
- if (ptr->prev)
- ptr->prev.setPointer(ptr->next.data());
- ptr->next = nullptr;
- ptr->prev.clear();
+ UNLINK_COMMON
+ if (ptr->next.tag() == QPropertyObserver::ObserverIsAlias)
+ ptr->aliasData = nullptr;
}
+/*!
+ \internal
+ Like unlink, but does not handle ObserverIsAlias.
+ Must only be called in places where we know that we are not dealing
+ with such an observer.
+ */
+void QPropertyObserverPointer::unlink_fast()
+{
+ Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsAlias);
+ UNLINK_COMMON
+}
+#undef UNLINK_COMMON
+
void QPropertyObserverPointer::setChangeHandler(QPropertyObserver::ChangeHandler changeHandler)
{
Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsPlaceholder);
@@ -666,7 +689,7 @@ struct [[nodiscard]] QPropertyObserverNodeProtector {
~QPropertyObserverNodeProtector() {
QPropertyObserverPointer d{static_cast<QPropertyObserver *>(&m_placeHolder)};
- d.unlink();
+ d.unlink_fast();
}
};
@@ -721,6 +744,8 @@ void QPropertyObserverPointer::notify(QUntypedPropertyData *propertyDataPtr)
case QPropertyObserver::ObserverIsPlaceholder:
// recursion is already properly handled somewhere else
break;
+ case QPropertyObserver::ObserverIsAlias:
+ break;
default: Q_UNREACHABLE();
}
observer = next;