summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qpropertybinding_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qpropertybinding_p.h')
-rw-r--r--src/corelib/kernel/qpropertybinding_p.h58
1 files changed, 46 insertions, 12 deletions
diff --git a/src/corelib/kernel/qpropertybinding_p.h b/src/corelib/kernel/qpropertybinding_p.h
index a2c733abd9..e03a23109a 100644
--- a/src/corelib/kernel/qpropertybinding_p.h
+++ b/src/corelib/kernel/qpropertybinding_p.h
@@ -66,14 +66,24 @@ class Q_CORE_EXPORT QPropertyBindingPrivate : public QSharedData
private:
friend struct QPropertyBasePointer;
+ using ObserverArray = std::array<QPropertyObserver, 4>;
+
+ // QSharedData is 4 bytes. Use the padding for the bools as we need 8 byte alignment below.
+ bool dirty = false;
+ bool updating = false;
+ bool hasStaticObserver = false;
+
QUntypedPropertyBinding::BindingEvaluationFunction evaluationFunction;
QPropertyObserverPointer firstObserver;
- std::array<QPropertyObserver, 4> inlineDependencyObservers;
+ union {
+ ObserverArray inlineDependencyObservers;
+ struct {
+ void *staticObserver;
+ void (*staticObserverCallback)(void*);
+ };
+ };
QScopedPointer<std::vector<QPropertyObserver>> heapObservers;
- // ### merge with inline dependency observer storage
- void *staticObserver = nullptr;
- void (*staticObserverCallback)(void*) = nullptr;
void *propertyDataPtr = nullptr;
@@ -82,9 +92,6 @@ private:
QMetaType metaType;
- bool dirty = false;
- bool updating = false;
-
public:
// public because the auto-tests access it, too.
size_t dependencyObserverCount = 0;
@@ -92,6 +99,7 @@ public:
QPropertyBindingPrivate(const QMetaType &metaType, QUntypedPropertyBinding::BindingEvaluationFunction evaluationFunction,
const QPropertyBindingSourceLocation &location)
: evaluationFunction(std::move(evaluationFunction))
+ , inlineDependencyObservers() // Explicit initialization required because of union
, location(location)
, metaType(metaType)
{}
@@ -99,7 +107,31 @@ public:
void setDirty(bool d) { dirty = d; }
void setProperty(void *propertyPtr) { propertyDataPtr = propertyPtr; }
- void setStaticObserver(void *observer, void (*callback)(void*)) { staticObserver = observer; staticObserverCallback = callback; }
+ void setStaticObserver(void *observer, void (*callback)(void*))
+ {
+ if (observer) {
+ if (!hasStaticObserver) {
+ if (dependencyObserverCount > 0) {
+ if (!heapObservers)
+ heapObservers.reset(new std::vector<QPropertyObserver>());
+ for (int i = 0, end = qMin(dependencyObserverCount, inlineDependencyObservers.size()); i < end; ++i)
+ heapObservers->push_back(std::move(inlineDependencyObservers[i]));
+ }
+ inlineDependencyObservers.~ObserverArray();
+ }
+
+ hasStaticObserver = true;
+ staticObserver = observer;
+ staticObserverCallback = callback;
+ } else if (hasStaticObserver) {
+ hasStaticObserver = false;
+ new (&inlineDependencyObservers) ObserverArray();
+ for (int i = 0, end = qMin(dependencyObserverCount, inlineDependencyObservers.size()); i < end; ++i) {
+ inlineDependencyObservers[i] = std::move(heapObservers->back());
+ heapObservers->pop_back();
+ }
+ }
+ }
void prependObserver(QPropertyObserverPointer observer) {
observer.ptr->prev = const_cast<QPropertyObserver **>(&firstObserver.ptr);
firstObserver = observer;
@@ -113,16 +145,18 @@ public:
}
void clearDependencyObservers() {
- for (size_t i = 0; i < inlineDependencyObservers.size(); ++i) {
- QPropertyObserver empty;
- qSwap(inlineDependencyObservers[i], empty);
+ if (!hasStaticObserver) {
+ 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()) {
+ if (!hasStaticObserver && dependencyObserverCount < inlineDependencyObservers.size()) {
++dependencyObserverCount;
return {&inlineDependencyObservers[dependencyObserverCount - 1]};
}