summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qproperty.cpp59
-rw-r--r--src/corelib/kernel/qproperty.h14
-rw-r--r--src/corelib/kernel/qproperty_p.h5
-rw-r--r--src/corelib/kernel/qpropertyprivate.h70
-rw-r--r--src/corelib/tools/qtaggedpointer.h6
5 files changed, 73 insertions, 81 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp
index ba91db3b5d..acb2de5369 100644
--- a/src/corelib/kernel/qproperty.cpp
+++ b/src/corelib/kernel/qproperty.cpp
@@ -51,7 +51,7 @@ QPropertyBase::QPropertyBase(QPropertyBase &&other, void *propertyDataPtr)
{
std::swap(d_ptr, other.d_ptr);
QPropertyBasePointer d{this};
- d.firstObserverPtr().set(nullptr);
+ d.setFirstObserver(nullptr);
if (auto binding = d.bindingPtr())
binding->propertyDataPtr = propertyDataPtr;
}
@@ -63,7 +63,7 @@ void QPropertyBase::moveAssign(QPropertyBase &&other, void *propertyDataPtr)
QPropertyBasePointer d{this};
auto observer = d.firstObserver();
- d.firstObserverPtr().set(nullptr);
+ d.setFirstObserver(nullptr);
if (auto binding = d.bindingPtr()) {
binding->unlinkAndDeref();
@@ -75,7 +75,7 @@ void QPropertyBase::moveAssign(QPropertyBase &&other, void *propertyDataPtr)
if (auto binding = d.bindingPtr())
binding->propertyDataPtr = propertyDataPtr;
- d.firstObserverPtr().set(const_cast<QPropertyObserver*>(observer.ptr));
+ d.setFirstObserver(observer.ptr);
// The caller will have to notify observers.
}
@@ -137,11 +137,31 @@ QPropertyBindingPrivate *QPropertyBasePointer::bindingPtr() const
return nullptr;
}
-QtPrivate::QPropertyTagPreservingPointerToPointer<QPropertyObserver> QPropertyBasePointer::firstObserverPtr() const
+void QPropertyBasePointer::addObserver(QPropertyObserver *observer)
{
- if (auto *binding = bindingPtr())
- return const_cast<QPropertyObserver**>(&binding->firstObserver.ptr);
- return &ptr->d_ptr;
+ if (auto *binding = bindingPtr()) {
+ observer->prev = &binding->firstObserver.ptr;
+ observer->next = binding->firstObserver.ptr;
+ if (observer->next)
+ observer->next->prev = &observer->next;
+ binding->firstObserver.ptr = observer;
+ } else {
+ auto firstObserver = reinterpret_cast<QPropertyObserver*>(ptr->d_ptr & ~QPropertyBase::FlagMask);
+ observer->prev = reinterpret_cast<QPropertyObserver**>(&ptr->d_ptr);
+ observer->next = firstObserver;
+ if (observer->next)
+ observer->next->prev = &observer->next;
+ }
+ setFirstObserver(observer);
+}
+
+void QPropertyBasePointer::setFirstObserver(QPropertyObserver *observer)
+{
+ if (auto *binding = bindingPtr()) {
+ binding->firstObserver.ptr = observer;
+ return;
+ }
+ ptr->d_ptr = reinterpret_cast<quintptr>(observer) | (ptr->d_ptr & QPropertyBase::FlagMask);
}
QPropertyObserverPointer QPropertyBasePointer::firstObserver() const
@@ -249,9 +269,9 @@ QPropertyObserver::QPropertyObserver(QPropertyObserver &&other)
std::swap(next, other.next);
std::swap(prev, other.prev);
if (next)
- next->prev = reinterpret_cast<quintptr*>(&next);
+ next->prev = &next;
if (prev)
- prev.set(this);
+ prev.setPointer(this);
}
QPropertyObserver &QPropertyObserver::operator=(QPropertyObserver &&other)
@@ -267,9 +287,9 @@ QPropertyObserver &QPropertyObserver::operator=(QPropertyObserver &&other)
std::swap(next, other.next);
std::swap(prev, other.prev);
if (next)
- next->prev = reinterpret_cast<quintptr*>(&next);
+ next->prev = &next;
if (prev)
- prev.set(this);
+ prev.setPointer(this);
return *this;
}
@@ -279,7 +299,7 @@ void QPropertyObserverPointer::unlink()
if (ptr->next)
ptr->next->prev = ptr->prev;
if (ptr->prev)
- ptr->prev.set(ptr->next.data());
+ ptr->prev.setPointer(ptr->next.pointer());
ptr->next = nullptr;
ptr->prev.clear();
}
@@ -287,13 +307,13 @@ void QPropertyObserverPointer::unlink()
void QPropertyObserverPointer::setChangeHandler(void (*changeHandler)(QPropertyObserver *))
{
ptr->changeHandler = changeHandler;
- ptr->next.setFlag(true);
+ ptr->next.setTag(QPropertyObserver::ObserverNotifiesChangeHandler);
}
void QPropertyObserverPointer::setBindingToMarkDirty(QPropertyBindingPrivate *binding)
{
ptr->bindingToMarkDirty = binding;
- ptr->next.setFlag(false);
+ ptr->next.setTag(QPropertyObserver::ObserverNotifiesBinding);
}
void QPropertyObserverPointer::notify(QPropertyBindingPrivate *triggeringBinding)
@@ -303,8 +323,8 @@ void QPropertyObserverPointer::notify(QPropertyBindingPrivate *triggeringBinding
auto observer = const_cast<QPropertyObserver*>(ptr);
while (observer) {
- auto * const next = observer->next.data();
- if (observer->next.flag()) {
+ auto * const next = observer->next.pointer();
+ if (observer->next.tag() == QPropertyObserver::ObserverNotifiesChangeHandler) {
if (!knownIfPropertyChanged && triggeringBinding) {
knownIfPropertyChanged = true;
@@ -328,12 +348,7 @@ void QPropertyObserverPointer::notify(QPropertyBindingPrivate *triggeringBinding
void QPropertyObserverPointer::observeProperty(QPropertyBasePointer property)
{
unlink();
- auto firstObserverPtr = property.firstObserverPtr();
- ptr->prev = firstObserverPtr;
- ptr->next = firstObserverPtr.get();
- if (ptr->next)
- ptr->next->prev = &ptr->next;
- firstObserverPtr.set(ptr);
+ property.addObserver(ptr);
}
void QPropertyObserverPointer::prependToBinding(QPropertyBindingPrivate *binding)
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h
index 5e1d8ec2f6..21b2ed0839 100644
--- a/src/corelib/kernel/qproperty.h
+++ b/src/corelib/kernel/qproperty.h
@@ -387,6 +387,13 @@ struct QPropertyObserverPointer;
struct Q_CORE_EXPORT QPropertyObserver
{
+ // Internal
+ enum ObserverTag {
+ ObserverNotifiesBinding = 0x0,
+ ObserverNotifiesChangeHandler = 0x1,
+ };
+ Q_DECLARE_FLAGS(ObserverTags, ObserverTag)
+
QPropertyObserver() = default;
QPropertyObserver(QPropertyObserver &&other);
QPropertyObserver &operator=(QPropertyObserver &&other);
@@ -402,10 +409,10 @@ protected:
private:
void setSource(QtPrivate::QPropertyBase &property);
- QtPrivate::QTaggedPointer<QPropertyObserver> next;
+ QTaggedPointer<QPropertyObserver, ObserverTags> next;
// prev is a pointer to the "next" element within the previous node, or to the "firstObserverPtr" if it is the
// first node.
- QtPrivate::QPropertyTagPreservingPointerToPointer<QPropertyObserver> prev;
+ QtPrivate::QTagPreservingPointerToPointer<QPropertyObserver, ObserverTags> prev;
union {
QPropertyBindingPrivate *bindingToMarkDirty = nullptr;
@@ -416,8 +423,11 @@ private:
QPropertyObserver &operator=(const QPropertyObserver &) = delete;
friend struct QPropertyObserverPointer;
+ friend struct QPropertyBasePointer;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QPropertyObserver::ObserverTags)
+
template <typename Functor>
class QPropertyChangeHandler : public QPropertyObserver
{
diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h
index 1b96e09d58..8815e66b69 100644
--- a/src/corelib/kernel/qproperty_p.h
+++ b/src/corelib/kernel/qproperty_p.h
@@ -65,7 +65,8 @@ struct Q_AUTOTEST_EXPORT QPropertyBasePointer
QPropertyBindingPrivate *bindingPtr() const;
- QtPrivate::QPropertyTagPreservingPointerToPointer<QPropertyObserver> firstObserverPtr() const;
+ void addObserver(QPropertyObserver *observer);
+ void setFirstObserver(QPropertyObserver *observer);
QPropertyObserverPointer firstObserver() const;
int observerCount() const;
@@ -93,7 +94,7 @@ struct QPropertyObserverPointer
explicit operator bool() const { return ptr != nullptr; }
- QPropertyObserverPointer nextObserver() const { return {ptr->next.data()}; }
+ QPropertyObserverPointer nextObserver() const { return {ptr->next.pointer()}; }
};
class QPropertyBindingErrorPrivate : public QSharedData
diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h
index 6d4a729845..22c5416197 100644
--- a/src/corelib/kernel/qpropertyprivate.h
+++ b/src/corelib/kernel/qpropertyprivate.h
@@ -53,6 +53,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/qtaggedpointer.h>
QT_BEGIN_NAMESPACE
@@ -161,85 +162,50 @@ struct QPropertyValueStorage<bool>
}
};
-template <typename T> class QTaggedPointer;
-
-template <typename T, quintptr Mask = 0x3>
-class QPropertyTagPreservingPointerToPointer
+template <typename T, typename Tag>
+class QTagPreservingPointerToPointer
{
- quintptr *data = nullptr;
-
public:
- QPropertyTagPreservingPointerToPointer() = default;
- QPropertyTagPreservingPointerToPointer(T **ptr)
- : data(reinterpret_cast<quintptr*>(ptr))
- {}
- QPropertyTagPreservingPointerToPointer(quintptr *ptr)
- : data(ptr)
+ QTagPreservingPointerToPointer() = default;
+
+ QTagPreservingPointerToPointer(T **ptr)
+ : d(reinterpret_cast<quintptr*>(ptr))
{}
- QPropertyTagPreservingPointerToPointer<T> &operator=(T **ptr)
+ QTagPreservingPointerToPointer<T, Tag> &operator=(T **ptr)
{
- data = reinterpret_cast<quintptr*>(ptr);
+ d = reinterpret_cast<quintptr*>(ptr);
return *this;
}
- QPropertyTagPreservingPointerToPointer<T> &operator=(QTaggedPointer<T> *ptr)
+ QTagPreservingPointerToPointer<T, Tag> &operator=(QTaggedPointer<T, Tag> *ptr)
{
- data = reinterpret_cast<quintptr*>(ptr);
+ d = reinterpret_cast<quintptr*>(ptr);
return *this;
}
void clear()
{
- data = nullptr;
+ d = nullptr;
}
- void set(T *ptr)
+ void setPointer(T *ptr)
{
- *data = (*data & Mask) | (reinterpret_cast<quintptr>(ptr) & ~Mask);
+ *d = (reinterpret_cast<quintptr>(ptr) & QTaggedPointer<T, Tag>::pointerMask()) | (*d & QTaggedPointer<T, Tag>::tagMask());
}
T *get() const
{
- return reinterpret_cast<T*>(*data & ~Mask);
+ return reinterpret_cast<T*>(*d & QTaggedPointer<T, Tag>::pointerMask());
}
- explicit operator bool() const { return data != nullptr; }
-};
-
-template <typename T>
-class QTaggedPointer
-{
-public:
- QTaggedPointer() = default;
- QTaggedPointer(T *ptr) : tagAndPointer(reinterpret_cast<quintptr>(ptr)) {}
-
- void setFlag(bool b)
+ explicit operator bool() const
{
- if (b)
- tagAndPointer |= Flag1Mask;
- else
- tagAndPointer &= ~Flag1Mask;
+ return d != nullptr;
}
- bool flag() const { return tagAndPointer & Flag1Mask; }
-
- QTaggedPointer &operator=(T *ptr)
- {
- quintptr tag = tagAndPointer & TagMask;
- tagAndPointer = reinterpret_cast<quintptr>(ptr) | tag;
- return *this;
- }
-
- T *data() const { return reinterpret_cast<T*>(tagAndPointer & ~TagMask); }
-
- explicit operator bool() const { return tagAndPointer & ~TagMask; }
- T *operator->() const { return data(); }
-
private:
- quintptr tagAndPointer = 0;
- static const quintptr Flag1Mask = 0x1;
- static const quintptr TagMask = 0x3;
+ quintptr *d = nullptr;
};
} // namespace QtPrivate
diff --git a/src/corelib/tools/qtaggedpointer.h b/src/corelib/tools/qtaggedpointer.h
index 6fa1e67acb..2d4d688824 100644
--- a/src/corelib/tools/qtaggedpointer.h
+++ b/src/corelib/tools/qtaggedpointer.h
@@ -73,13 +73,13 @@ namespace QtPrivate {
template <typename T, typename Tag = typename QtPrivate::TagInfo<T>::TagType>
class QTaggedPointer
{
- static constexpr quintptr tagMask() { return QtPrivate::TagInfo<T>::alignment - 1; }
- static constexpr quintptr pointerMask() { return ~tagMask(); }
-
public:
using Type = T;
using TagType = Tag;
+ static constexpr quintptr tagMask() { return QtPrivate::TagInfo<T>::alignment - 1; }
+ static constexpr quintptr pointerMask() { return ~tagMask(); }
+
explicit QTaggedPointer(Type *pointer = nullptr, TagType tag = TagType()) noexcept
: d(quintptr(pointer))
{