diff options
Diffstat (limited to 'src/corelib/kernel/qpropertyprivate.h')
-rw-r--r-- | src/corelib/kernel/qpropertyprivate.h | 74 |
1 files changed, 41 insertions, 33 deletions
diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h index ab69e966cf..a8456721d0 100644 --- a/src/corelib/kernel/qpropertyprivate.h +++ b/src/corelib/kernel/qpropertyprivate.h @@ -18,6 +18,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qtaggedpointer.h> #include <QtCore/qmetatype.h> +#include <QtCore/qcontainerfwd.h> #include <functional> @@ -28,13 +29,20 @@ class QBindingStorage; template<typename Class, typename T, auto Offset, auto Setter, auto Signal, auto Getter> class QObjectCompatProperty; +struct QBindingObserverPtr; +using PendingBindingObserverList = QVarLengthArray<QBindingObserverPtr>; + namespace QtPrivate { // QPropertyBindingPrivatePtr operates on a RefCountingMixin solely so that we can inline // the constructor and copy constructor struct RefCounted { + + int refCount() const { return ref; } + void addRef() { ++ref; } + bool deref() { return --ref != 0; } + +private: int ref = 0; - void addRef() {++ref;} - bool deref() {--ref; return ref;} }; } @@ -57,7 +65,7 @@ public: QPropertyBindingPrivatePtr() noexcept : d(nullptr) { } ~QPropertyBindingPrivatePtr() { - if (d && (--d->ref == 0)) + if (d && !d->deref()) destroyAndFreeMemory(); } Q_CORE_EXPORT void destroyAndFreeMemory(); @@ -78,7 +86,7 @@ public: reset(o); return *this; } - QPropertyBindingPrivatePtr(QPropertyBindingPrivatePtr &&o) noexcept : d(qExchange(o.d, nullptr)) {} + QPropertyBindingPrivatePtr(QPropertyBindingPrivatePtr &&o) noexcept : d(std::exchange(o.d, nullptr)) {} QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QPropertyBindingPrivatePtr) operator bool () const noexcept { return d != nullptr; } @@ -87,43 +95,38 @@ public: void swap(QPropertyBindingPrivatePtr &other) noexcept { qt_ptr_swap(d, other.d); } - friend bool operator==(const QPropertyBindingPrivatePtr &p1, const QPropertyBindingPrivatePtr &p2) noexcept - { return p1.d == p2.d; } - friend bool operator!=(const QPropertyBindingPrivatePtr &p1, const QPropertyBindingPrivatePtr &p2) noexcept - { return p1.d != p2.d; } - friend bool operator==(const QPropertyBindingPrivatePtr &p1, const T *ptr) noexcept - { return p1.d == ptr; } - friend bool operator!=(const QPropertyBindingPrivatePtr &p1, const T *ptr) noexcept - { return p1.d != ptr; } - friend bool operator==(const T *ptr, const QPropertyBindingPrivatePtr &p2) noexcept - { return ptr == p2.d; } - friend bool operator!=(const T *ptr, const QPropertyBindingPrivatePtr &p2) noexcept - { return ptr != p2.d; } - friend bool operator==(const QPropertyBindingPrivatePtr &p1, std::nullptr_t) noexcept - { return !p1; } - friend bool operator!=(const QPropertyBindingPrivatePtr &p1, std::nullptr_t) noexcept - { return p1; } - friend bool operator==(std::nullptr_t, const QPropertyBindingPrivatePtr &p2) noexcept - { return !p2; } - friend bool operator!=(std::nullptr_t, const QPropertyBindingPrivatePtr &p2) noexcept - { return p2; } - private: + friend bool comparesEqual(const QPropertyBindingPrivatePtr &lhs, + const QPropertyBindingPrivatePtr &rhs) noexcept + { return lhs.d == rhs.d; } + Q_DECLARE_EQUALITY_COMPARABLE(QPropertyBindingPrivatePtr) + friend bool comparesEqual(const QPropertyBindingPrivatePtr &lhs, + const T *rhs) noexcept + { return lhs.d == rhs; } + Q_DECLARE_EQUALITY_COMPARABLE(QPropertyBindingPrivatePtr, T*) + friend bool comparesEqual(const QPropertyBindingPrivatePtr &lhs, + std::nullptr_t) noexcept + { return !lhs; } + Q_DECLARE_EQUALITY_COMPARABLE(QPropertyBindingPrivatePtr, std::nullptr_t) + QtPrivate::RefCounted *d; }; class QUntypedPropertyBinding; class QPropertyBindingPrivate; struct QPropertyBindingDataPointer; +class QPropertyObserver; struct QPropertyObserverPointer; class QUntypedPropertyData { -public: - // sentinel to check whether a class inherits QUntypedPropertyData - struct InheritsQUntypedPropertyData {}; }; +namespace QtPrivate { +template <typename T> +using IsUntypedPropertyData = std::enable_if_t<std::is_base_of_v<QUntypedPropertyData, T>, bool>; +} + template <typename T> class QPropertyData; @@ -189,8 +192,7 @@ struct BindingFunctionVTable return true; } else { // Our code will never instantiate this - Q_UNREACHABLE(); - return false; + Q_UNREACHABLE_RETURN(false); } }, /*destroy*/[](void *f){ static_cast<Callable *>(f)->~Callable(); }, @@ -299,17 +301,23 @@ private: { quintptr &d = d_ptr; if (isNotificationDelayed()) - return reinterpret_cast<QPropertyProxyBindingData *>(d_ptr & ~(BindingBit|DelayedNotificationBit))->d_ptr; + return proxyData()->d_ptr; return d; } quintptr d() const { return d_ref(); } + QPropertyProxyBindingData *proxyData() const + { + Q_ASSERT(isNotificationDelayed()); + return reinterpret_cast<QPropertyProxyBindingData *>(d_ptr & ~(BindingBit|DelayedNotificationBit)); + } void registerWithCurrentlyEvaluatingBinding_helper(BindingEvaluationState *currentBinding) const; void removeBinding_helper(); enum NotificationResult { Delayed, Evaluated }; NotificationResult notifyObserver_helper( - QUntypedPropertyData *propertyDataPtr, QPropertyObserverPointer observer, - QBindingStorage *storage) const; + QUntypedPropertyData *propertyDataPtr, QBindingStorage *storage, + QPropertyObserverPointer observer, + PendingBindingObserverList &bindingObservers) const; }; template <typename T, typename Tag> |