diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-09-28 10:32:00 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-09-29 20:32:42 +0200 |
commit | 04641454beb27f667062dbf79116729f159b0041 (patch) | |
tree | 2664d504dbb17f10792831f6e3b85e31640f3fba /src/corelib | |
parent | 6b4e0c5803b4b8b4396791ba436d9692195993d6 (diff) |
Disable moving of QProperty
The semantics are not very intuitive, and it opens a can of worms
with regards to what should happen with observers that observe
that property.
Change-Id: I6fb00b7693904b968224cc87d098bbd0ea776ba3
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/kernel/qproperty.cpp | 47 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty.h | 10 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty_p.h | 12 | ||||
-rw-r--r-- | src/corelib/kernel/qpropertyprivate.h | 4 |
4 files changed, 21 insertions, 52 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 4fdf0d8100..3a2c8dcc0c 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -196,39 +196,6 @@ QMetaType QUntypedPropertyBinding::valueMetaType() const return d->valueMetaType(); } -QPropertyBindingData::QPropertyBindingData(QPropertyBindingData &&other, QUntypedPropertyData *propertyDataPtr) -{ - std::swap(d_ptr, other.d_ptr); - QPropertyBindingDataPointer d{this}; - d.setFirstObserver(nullptr); - if (auto binding = d.bindingPtr()) - binding->setProperty(propertyDataPtr); -} - -void QPropertyBindingData::moveAssign(QPropertyBindingData &&other, QUntypedPropertyData *propertyDataPtr) -{ - if (&other == this) - return; - - QPropertyBindingDataPointer d{this}; - auto observer = d.firstObserver(); - d.setFirstObserver(nullptr); - - if (auto binding = d.bindingPtr()) { - binding->unlinkAndDeref(); - d_ptr &= FlagMask; - } - - std::swap(d_ptr, other.d_ptr); - - if (auto binding = d.bindingPtr()) - binding->setProperty(propertyDataPtr); - - d.setFirstObserver(observer.ptr); - - // The caller will have to notify observers. -} - QPropertyBindingData::~QPropertyBindingData() { QPropertyBindingDataPointer d{this}; @@ -286,6 +253,12 @@ QUntypedPropertyBinding QPropertyBindingData::setBinding(const QUntypedPropertyB return QUntypedPropertyBinding(oldBinding.data()); } +QPropertyBindingData::QPropertyBindingData(QPropertyBindingData &&other) : d_ptr(std::exchange(other.d_ptr, 0)) +{ + QPropertyBindingDataPointer d{this}; + d.fixupFirstObserverAfterMove(); +} + QPropertyBindingPrivate *QPropertyBindingData::binding() const { QPropertyBindingDataPointer d{this}; @@ -694,12 +667,6 @@ QString QPropertyBindingError::description() const */ /*! - \fn template <typename T> QProperty<T> &QProperty<T>::operator=(QProperty &&other) - - Move-assigns \a other to this QProperty instance. -*/ - -/*! \fn template <typename T> QProperty<T>::QProperty(const QPropertyBinding<T> &binding) Constructs a property that is tied to the provided \a binding expression. The @@ -1395,7 +1362,7 @@ struct QBindingStoragePrivate if (index == newData->size) index = 0; } - new (pp + index) Pair{p->data, QPropertyBindingData(std::move(p->bindingData), p->data)}; + new (pp + index) Pair{p->data, QPropertyBindingData(std::move(p->bindingData))}; } } // data has been moved, no need to call destructors on old Pairs diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 09b2642e73..156696dace 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -315,7 +315,6 @@ public: QProperty() = default; explicit QProperty(parameter_type initialValue) : QPropertyData<T>(initialValue) {} explicit QProperty(rvalue_ref initialValue) : QPropertyData<T>(std::move(initialValue)) {} - QProperty(QProperty &&other) : QPropertyData<T>(std::move(other.val)), d(std::move(other.d), this) { notify(); } explicit QProperty(const QPropertyBinding<T> &binding) : QProperty() { setBinding(binding); } @@ -329,13 +328,6 @@ public: template <typename Functor> explicit QProperty(Functor &&f); #endif - QProperty &operator=(QProperty &&other) - { - this->val = std::move(other.val); - d.moveAssign(std::move(other.d), this); - notify(); - return *this; - } ~QProperty() = default; parameter_type value() const @@ -460,7 +452,7 @@ private: d.notifyObservers(this); } - Q_DISABLE_COPY(QProperty) + Q_DISABLE_COPY_MOVE(QProperty) }; namespace Qt { diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index 614756a670..1bf308e8ea 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -81,6 +81,7 @@ struct Q_AUTOTEST_EXPORT QPropertyBindingDataPointer observer->prev = reinterpret_cast<QPropertyObserver**>(&(ptr->d_ptr)); ptr->d_ptr = (reinterpret_cast<quintptr>(observer) & ~QtPrivate::QPropertyBindingData::FlagMask); } + void fixupFirstObserverAfterMove() const; void addObserver(QPropertyObserver *observer); void setFirstObserver(QPropertyObserver *observer); QPropertyObserverPointer firstObserver() const; @@ -293,6 +294,17 @@ inline void QPropertyBindingDataPointer::setFirstObserver(QPropertyObserver *obs ptr->d_ptr = reinterpret_cast<quintptr>(observer) | (ptr->d_ptr & QtPrivate::QPropertyBindingData::FlagMask); } +inline void QPropertyBindingDataPointer::fixupFirstObserverAfterMove() const +{ + // If QPropertyBindingData has been moved, and it has an observer + // we have to adjust the firstObesrver's prev pointer to point to + // the moved to QPropertyBindingData's d_ptr + if (ptr->d_ptr & QtPrivate::QPropertyBindingData::BindingBit) + return; // nothing to do if the observer is stored in the binding + if (auto observer = firstObserver()) + observer.ptr->prev = reinterpret_cast<QPropertyObserver**>(&(ptr->d_ptr)); +} + inline QPropertyObserverPointer QPropertyBindingDataPointer::firstObserver() const { if (auto *binding = bindingPtr()) diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h index dd344c209a..26877e0315 100644 --- a/src/corelib/kernel/qpropertyprivate.h +++ b/src/corelib/kernel/qpropertyprivate.h @@ -88,12 +88,10 @@ class Q_CORE_EXPORT QPropertyBindingData Q_DISABLE_COPY(QPropertyBindingData) public: QPropertyBindingData() = default; - QPropertyBindingData(QPropertyBindingData &&other, QUntypedPropertyData *propertyDataPtr); + QPropertyBindingData(QPropertyBindingData &&other); QPropertyBindingData &operator=(QPropertyBindingData &&other) = delete; ~QPropertyBindingData(); - void moveAssign(QPropertyBindingData &&other, QUntypedPropertyData *propertyDataPtr); - bool hasBinding() const { return d_ptr & BindingBit; } QUntypedPropertyBinding setBinding(const QUntypedPropertyBinding &newBinding, |