summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qproperty.cpp24
-rw-r--r--src/corelib/kernel/qproperty.h14
-rw-r--r--src/corelib/kernel/qproperty_p.h2
-rw-r--r--src/corelib/kernel/qpropertybinding.cpp11
-rw-r--r--src/corelib/kernel/qpropertybinding_p.h46
-rw-r--r--src/corelib/kernel/qpropertyprivate.h2
-rw-r--r--tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp8
7 files changed, 64 insertions, 43 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp
index 2dbe8b6310..18580fa756 100644
--- a/src/corelib/kernel/qproperty.cpp
+++ b/src/corelib/kernel/qproperty.cpp
@@ -53,7 +53,7 @@ QPropertyBase::QPropertyBase(QPropertyBase &&other, void *propertyDataPtr)
QPropertyBasePointer d{this};
d.setFirstObserver(nullptr);
if (auto binding = d.bindingPtr())
- binding->propertyDataPtr = propertyDataPtr;
+ binding->setProperty(propertyDataPtr);
}
void QPropertyBase::moveAssign(QPropertyBase &&other, void *propertyDataPtr)
@@ -73,7 +73,7 @@ void QPropertyBase::moveAssign(QPropertyBase &&other, void *propertyDataPtr)
std::swap(d_ptr, other.d_ptr);
if (auto binding = d.bindingPtr())
- binding->propertyDataPtr = propertyDataPtr;
+ binding->setProperty(propertyDataPtr);
d.setFirstObserver(observer.ptr);
@@ -111,10 +111,10 @@ QUntypedPropertyBinding QPropertyBase::setBinding(const QUntypedPropertyBinding
newBinding.data()->ref.ref();
d_ptr = (d_ptr & FlagMask) | reinterpret_cast<quintptr>(newBinding.data());
d_ptr |= BindingBit;
- newBinding->dirty = true;
- newBinding->propertyDataPtr = propertyDataPtr;
+ newBinding->setDirty(true);
+ newBinding->setProperty(propertyDataPtr);
if (observer)
- observer.prependToBinding(newBinding.data());
+ newBinding->prependObserver(observer);
} else {
d_ptr &= ~BindingBit;
}
@@ -175,11 +175,10 @@ static thread_local BindingEvaluationState *currentBindingEvaluationState = null
BindingEvaluationState::BindingEvaluationState(QPropertyBindingPrivate *binding)
: binding(binding)
- , dependencyObservers(&binding->dependencyObservers)
{
previousState = currentBindingEvaluationState;
currentBindingEvaluationState = this;
- dependencyObservers->clear();
+ binding->clearDependencyObservers();
}
BindingEvaluationState::~BindingEvaluationState()
@@ -222,8 +221,7 @@ void QPropertyBase::registerWithCurrentlyEvaluatingBinding() const
QPropertyBasePointer d{this};
- currentState->dependencyObservers->append(QPropertyObserver());
- QPropertyObserverPointer dependencyObserver{&(*currentState->dependencyObservers)[currentState->dependencyObservers->size() - 1]};
+ QPropertyObserverPointer dependencyObserver = currentState->binding->allocateDependencyObserver();
dependencyObserver.setBindingToMarkDirty(currentState->binding);
dependencyObserver.observeProperty(d);
}
@@ -263,6 +261,8 @@ QPropertyObserver::~QPropertyObserver()
d.unlink();
}
+QPropertyObserver::QPropertyObserver() = default;
+
QPropertyObserver::QPropertyObserver(QPropertyObserver &&other)
{
std::swap(bindingToMarkDirty, other.bindingToMarkDirty);
@@ -351,12 +351,6 @@ void QPropertyObserverPointer::observeProperty(QPropertyBasePointer property)
property.addObserver(ptr);
}
-void QPropertyObserverPointer::prependToBinding(QPropertyBindingPrivate *binding)
-{
- ptr->prev = const_cast<QPropertyObserver **>(&binding->firstObserver.ptr);
- binding->firstObserver = *this;
-}
-
QPropertyBindingError::QPropertyBindingError(Type type)
{
if (type != NoError) {
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h
index 21b2ed0839..338c7bbeec 100644
--- a/src/corelib/kernel/qproperty.h
+++ b/src/corelib/kernel/qproperty.h
@@ -137,12 +137,10 @@ public:
QMetaType valueMetaType() const;
- void setDirty(bool dirty = true);
-
-private:
explicit QUntypedPropertyBinding(const QPropertyBindingPrivatePtr &priv);
+private:
friend class QtPrivate::QPropertyBase;
- friend struct QPropertyBindingPrivate;
+ friend class QPropertyBindingPrivate;
template <typename> friend class QPropertyBinding;
QPropertyBindingPrivatePtr d;
};
@@ -357,7 +355,7 @@ private:
friend struct QPropertyBasePointer;
friend class QPropertyBinding<T>;
- friend struct QPropertyObserver;
+ friend class QPropertyObserver;
// Mutable because querying for the value may require evalating the binding expression, calling
// non-const functions on QPropertyBase.
mutable QtPrivate::QPropertyValueStorage<T> d;
@@ -385,8 +383,9 @@ namespace Qt {
struct QPropertyObserverPrivate;
struct QPropertyObserverPointer;
-struct Q_CORE_EXPORT QPropertyObserver
+class Q_CORE_EXPORT QPropertyObserver
{
+public:
// Internal
enum ObserverTag {
ObserverNotifiesBinding = 0x0,
@@ -394,7 +393,7 @@ struct Q_CORE_EXPORT QPropertyObserver
};
Q_DECLARE_FLAGS(ObserverTags, ObserverTag)
- QPropertyObserver() = default;
+ QPropertyObserver();
QPropertyObserver(QPropertyObserver &&other);
QPropertyObserver &operator=(QPropertyObserver &&other);
~QPropertyObserver();
@@ -424,6 +423,7 @@ private:
friend struct QPropertyObserverPointer;
friend struct QPropertyBasePointer;
+ friend class QPropertyBindingPrivate;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QPropertyObserver::ObserverTags)
diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h
index 1fbe5231fe..a50ae0dee1 100644
--- a/src/corelib/kernel/qproperty_p.h
+++ b/src/corelib/kernel/qproperty_p.h
@@ -90,7 +90,6 @@ struct QPropertyObserverPointer
void notify(QPropertyBindingPrivate *triggeringBinding);
void observeProperty(QPropertyBasePointer property);
- void prependToBinding(QPropertyBindingPrivate *binding);
explicit operator bool() const { return ptr != nullptr; }
@@ -110,7 +109,6 @@ struct BindingEvaluationState
BindingEvaluationState(QPropertyBindingPrivate *binding);
~BindingEvaluationState();
QPropertyBindingPrivate *binding;
- QVarLengthArray<QPropertyObserver, 4> *dependencyObservers = nullptr;
BindingEvaluationState *previousState = nullptr;
};
diff --git a/src/corelib/kernel/qpropertybinding.cpp b/src/corelib/kernel/qpropertybinding.cpp
index 78d24cbdc1..aa7bf1d022 100644
--- a/src/corelib/kernel/qpropertybinding.cpp
+++ b/src/corelib/kernel/qpropertybinding.cpp
@@ -152,21 +152,14 @@ QPropertyBindingError QUntypedPropertyBinding::error() const
{
if (!d)
return QPropertyBindingError();
- return d->error;
+ return d->bindingError();
}
QMetaType QUntypedPropertyBinding::valueMetaType() const
{
if (!d)
return QMetaType();
- return d->metaType;
-}
-
-void QUntypedPropertyBinding::setDirty(bool dirty)
-{
- if (!d)
- return;
- d->dirty = dirty;
+ return d->valueMetaType();
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qpropertybinding_p.h b/src/corelib/kernel/qpropertybinding_p.h
index 92638c92cc..66e969547c 100644
--- a/src/corelib/kernel/qpropertybinding_p.h
+++ b/src/corelib/kernel/qpropertybinding_p.h
@@ -53,8 +53,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qshareddata.h>
-#include <QtCore/qvarlengtharray.h>
-#include <memory>
+#include <QtCore/qscopedpointer.h>
#include <vector>
#include <functional>
@@ -62,12 +61,16 @@
QT_BEGIN_NAMESPACE
-struct QPropertyBindingPrivate : public QSharedData
+class Q_CORE_EXPORT QPropertyBindingPrivate : public QSharedData
{
+private:
+ friend struct QPropertyBasePointer;
+
QUntypedPropertyBinding::BindingEvaluationFunction evaluationFunction;
QPropertyObserverPointer firstObserver;
- QVarLengthArray<QPropertyObserver, 4> dependencyObservers;
+ std::array<QPropertyObserver, 4> inlineDependencyObservers;
+ QScopedPointer<std::vector<QPropertyObserver>> heapObservers;
void *propertyDataPtr = nullptr;
@@ -79,6 +82,10 @@ struct QPropertyBindingPrivate : public QSharedData
bool dirty = false;
bool updating = false;
+public:
+ // public because the auto-tests access it, too.
+ size_t dependencyObserverCount = 0;
+
QPropertyBindingPrivate(const QMetaType &metaType, QUntypedPropertyBinding::BindingEvaluationFunction evaluationFunction,
const QPropertyBindingSourceLocation &location)
: evaluationFunction(std::move(evaluationFunction))
@@ -87,6 +94,37 @@ struct QPropertyBindingPrivate : public QSharedData
{}
virtual ~QPropertyBindingPrivate();
+ void setDirty(bool d) { dirty = d; }
+ void setProperty(void *propertyPtr) { propertyDataPtr = propertyPtr; }
+ void prependObserver(QPropertyObserverPointer observer) {
+ observer.ptr->prev = const_cast<QPropertyObserver **>(&firstObserver.ptr);
+ firstObserver = observer;
+ }
+
+ void clearDependencyObservers() {
+ for (size_t i = 0; i < inlineDependencyObservers.size(); ++i) {
+ QPropertyObserver empty;
+ qSwap(inlineDependencyObservers[i], empty);
+ }
+ if (heapObservers)
+ heapObservers->clear();
+ dependencyObserverCount = 0;
+ }
+ QPropertyObserverPointer allocateDependencyObserver() {
+ if (dependencyObserverCount < inlineDependencyObservers.size()) {
+ ++dependencyObserverCount;
+ return {&inlineDependencyObservers[dependencyObserverCount - 1]};
+ }
+ ++dependencyObserverCount;
+ if (!heapObservers)
+ heapObservers.reset(new std::vector<QPropertyObserver>());
+ return {&heapObservers->emplace_back()};
+ }
+
+ QPropertyBindingSourceLocation sourceLocation() const { return location; }
+ QPropertyBindingError bindingError() const { return error; }
+ QMetaType valueMetaType() const { return metaType; }
+
void unlinkAndDeref();
void markDirtyAndNotifyObservers();
diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h
index 22c5416197..b4f2cd5154 100644
--- a/src/corelib/kernel/qpropertyprivate.h
+++ b/src/corelib/kernel/qpropertyprivate.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
class QUntypedPropertyBinding;
-struct QPropertyBindingPrivate;
+class QPropertyBindingPrivate;
using QPropertyBindingPrivatePtr = QExplicitlySharedDataPointer<QPropertyBindingPrivate>;
struct QPropertyBasePointer;
diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
index 942865f3a3..d4c5741814 100644
--- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
+++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
@@ -220,13 +220,11 @@ void tst_QProperty::avoidDependencyAllocationAfterFirstEval()
QCOMPARE(propWithBinding.value(), int(11));
QVERIFY(QPropertyBasePointer::get(propWithBinding).bindingPtr());
- QCOMPARE(QPropertyBasePointer::get(propWithBinding).bindingPtr()->dependencyObservers.size(), 2);
- QVERIFY(QPropertyBasePointer::get(propWithBinding).bindingPtr()->dependencyObservers.capacity() >= 2);
+ QCOMPARE(QPropertyBasePointer::get(propWithBinding).bindingPtr()->dependencyObserverCount, 2);
firstDependency = 100;
QCOMPARE(propWithBinding.value(), int(110));
- QCOMPARE(QPropertyBasePointer::get(propWithBinding).bindingPtr()->dependencyObservers.size(), 2);
- QVERIFY(QPropertyBasePointer::get(propWithBinding).bindingPtr()->dependencyObservers.capacity() >= 2);
+ QCOMPARE(QPropertyBasePointer::get(propWithBinding).bindingPtr()->dependencyObserverCount, 2);
}
void tst_QProperty::propertyArrays()
@@ -493,7 +491,7 @@ void tst_QProperty::bindingSourceLocation()
#if defined(QT_PROPERTY_COLLECT_BINDING_LOCATION)
auto bindingLine = std::experimental::source_location::current().line() + 1;
auto binding = Qt::makePropertyBinding([]() { return 42; });
- QCOMPARE(QPropertyBindingPrivate::get(binding)->location.line, bindingLine);
+ QCOMPARE(QPropertyBindingPrivate::get(binding)->sourceLocation().line, bindingLine);
#else
QSKIP("Skipping this in the light of missing binding source location support");
#endif