summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/kernel.pri4
-rw-r--r--src/corelib/kernel/qproperty.cpp208
-rw-r--r--src/corelib/kernel/qproperty_p.h165
-rw-r--r--src/corelib/kernel/qpropertybinding.cpp192
-rw-r--r--src/corelib/kernel/qpropertybinding_p.h194
-rw-r--r--src/corelib/kernel/qpropertyprivate.h2
6 files changed, 325 insertions, 440 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index fc48ef430e..a493260c50 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -46,8 +46,7 @@ HEADERS += \
kernel/qtestsupport_core.h \
kernel/qproperty.h \
kernel/qpropertyprivate.h \
- kernel/qproperty_p.h \
- kernel/qpropertybinding_p.h
+ kernel/qproperty_p.h
SOURCES += \
kernel/qabstracteventdispatcher.cpp \
@@ -77,7 +76,6 @@ SOURCES += \
kernel/qsystemerror.cpp \
kernel/qtestsupport_core.cpp \
kernel/qproperty.cpp \
- kernel/qpropertybinding.cpp
win32 {
SOURCES += \
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp
index 9374ce3a74..3bac73909a 100644
--- a/src/corelib/kernel/qproperty.cpp
+++ b/src/corelib/kernel/qproperty.cpp
@@ -39,7 +39,6 @@
#include "qproperty.h"
#include "qproperty_p.h"
-#include "qpropertybinding_p.h"
#include <qscopedvaluerollback.h>
@@ -47,6 +46,166 @@ QT_BEGIN_NAMESPACE
using namespace QtPrivate;
+void QPropertyBasePointer::addObserver(QPropertyObserver *observer)
+{
+ 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);
+}
+
+QPropertyBindingPrivate::~QPropertyBindingPrivate()
+{
+ if (firstObserver)
+ firstObserver.unlink();
+ if (!hasStaticObserver)
+ inlineDependencyObservers.~ObserverArray(); // Explicit because of union.
+}
+
+void QPropertyBindingPrivate::unlinkAndDeref()
+{
+ propertyDataPtr = nullptr;
+ if (!ref.deref())
+ delete this;
+}
+
+void QPropertyBindingPrivate::markDirtyAndNotifyObservers()
+{
+ if (dirty)
+ return;
+ dirty = true;
+ if (firstObserver)
+ firstObserver.notify(this, propertyDataPtr);
+ if (hasStaticObserver) {
+ if (isBool) {
+ auto propertyPtr = reinterpret_cast<QPropertyBase *>(propertyDataPtr);
+ bool oldValue = propertyPtr->extraBit();
+ staticObserverCallback(staticObserver, &oldValue);
+ } else {
+ staticObserverCallback(staticObserver, propertyDataPtr);
+ }
+ }
+}
+
+bool QPropertyBindingPrivate::evaluateIfDirtyAndReturnTrueIfValueChanged()
+{
+ if (!dirty)
+ return false;
+
+ if (updating) {
+ error = QPropertyBindingError(QPropertyBindingError::BindingLoop);
+ return false;
+ }
+
+ /*
+ * Evaluating the binding might lead to the binding being broken. This can
+ * cause ref to reach zero at the end of the function. However, the
+ * updateGuard's destructor will then still trigger, trying to set the
+ * updating bool to its old value
+ * To prevent this, we create a QPropertyBindingPrivatePtr which ensures
+ * that the object is still alive when updateGuard's dtor runs.
+ */
+ QPropertyBindingPrivatePtr keepAlive {this};
+ QScopedValueRollback<bool> updateGuard(updating, true);
+
+ BindingEvaluationState evaluationFrame(this);
+
+ bool changed = false;
+
+ if (hasStaticObserver && staticGuardCallback) {
+ if (isBool) {
+ auto propertyPtr = reinterpret_cast<QPropertyBase *>(propertyDataPtr);
+ bool newValue = propertyPtr->extraBit();
+ changed = staticGuardCallback(metaType, &newValue, evaluationFunction, staticObserver);
+ if (changed && !error.hasError())
+ propertyPtr->setExtraBit(newValue);
+ } else {
+ changed = staticGuardCallback(metaType, propertyDataPtr, evaluationFunction, staticObserver);
+ }
+ } else {
+ if (isBool) {
+ auto propertyPtr = reinterpret_cast<QPropertyBase *>(propertyDataPtr);
+ bool newValue = propertyPtr->extraBit();
+ changed = evaluationFunction(metaType, &newValue);
+ if (changed && !error.hasError())
+ propertyPtr->setExtraBit(newValue);
+ } else {
+ changed = evaluationFunction(metaType, propertyDataPtr);
+ }
+ }
+
+ dirty = false;
+ return changed;
+}
+
+QUntypedPropertyBinding::QUntypedPropertyBinding() = default;
+
+QUntypedPropertyBinding::QUntypedPropertyBinding(const QMetaType &metaType, QUntypedPropertyBinding::BindingEvaluationFunction function,
+ const QPropertyBindingSourceLocation &location)
+{
+ d = new QPropertyBindingPrivate(metaType, std::move(function), std::move(location));
+}
+
+QUntypedPropertyBinding::QUntypedPropertyBinding(QUntypedPropertyBinding &&other)
+ : d(std::move(other.d))
+{
+}
+
+QUntypedPropertyBinding::QUntypedPropertyBinding(const QUntypedPropertyBinding &other)
+ : d(other.d)
+{
+}
+
+QUntypedPropertyBinding &QUntypedPropertyBinding::operator=(const QUntypedPropertyBinding &other)
+{
+ d = other.d;
+ return *this;
+}
+
+QUntypedPropertyBinding &QUntypedPropertyBinding::operator=(QUntypedPropertyBinding &&other)
+{
+ d = std::move(other.d);
+ return *this;
+}
+
+QUntypedPropertyBinding::QUntypedPropertyBinding(QPropertyBindingPrivate *priv)
+ : d(priv)
+{
+}
+
+QUntypedPropertyBinding::~QUntypedPropertyBinding()
+{
+}
+
+bool QUntypedPropertyBinding::isNull() const
+{
+ return !d;
+}
+
+QPropertyBindingError QUntypedPropertyBinding::error() const
+{
+ if (!d)
+ return QPropertyBindingError();
+ return d->bindingError();
+}
+
+QMetaType QUntypedPropertyBinding::valueMetaType() const
+{
+ if (!d)
+ return QMetaType();
+ return d->valueMetaType();
+}
+
QPropertyBase::QPropertyBase(QPropertyBase &&other, void *propertyDataPtr)
{
std::swap(d_ptr, other.d_ptr);
@@ -141,53 +300,6 @@ QPropertyBindingPrivate *QPropertyBase::binding()
return nullptr;
}
-QPropertyBindingPrivate *QPropertyBasePointer::bindingPtr() const
-{
- if (ptr->d_ptr & QPropertyBase::BindingBit)
- return reinterpret_cast<QPropertyBindingPrivate*>(ptr->d_ptr & ~QPropertyBase::FlagMask);
- return nullptr;
-}
-
-void QPropertyBasePointer::setObservers(QPropertyObserver *observer)
-{
- observer->prev = reinterpret_cast<QPropertyObserver**>(&(ptr->d_ptr));
- ptr->d_ptr = (reinterpret_cast<quintptr>(observer) & ~QPropertyBase::FlagMask);
-}
-
-void QPropertyBasePointer::addObserver(QPropertyObserver *observer)
-{
- 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
-{
- if (auto *binding = bindingPtr())
- return binding->firstObserver;
- return {reinterpret_cast<QPropertyObserver*>(ptr->d_ptr & ~QPropertyBase::FlagMask)};
-}
-
static thread_local BindingEvaluationState *currentBindingEvaluationState = nullptr;
BindingEvaluationState::BindingEvaluationState(QPropertyBindingPrivate *binding)
diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h
index 7b9d7c207f..159c652657 100644
--- a/src/corelib/kernel/qproperty_p.h
+++ b/src/corelib/kernel/qproperty_p.h
@@ -52,20 +52,35 @@
//
#include <qglobal.h>
+#include <qproperty.h>
+
#include <qvarlengtharray.h>
+#include <qscopedpointer.h>
+#include <vector>
-#include "qproperty.h"
QT_BEGIN_NAMESPACE
+// Keep all classes related to QProperty in one compilation unit. Performance of this code is crucial and
+// we need to allow the compiler to inline where it makes sense.
+
// This is a helper "namespace"
struct Q_AUTOTEST_EXPORT QPropertyBasePointer
{
const QtPrivate::QPropertyBase *ptr = nullptr;
- QPropertyBindingPrivate *bindingPtr() const;
+ QPropertyBindingPrivate *bindingPtr() const
+ {
+ if (ptr->d_ptr & QtPrivate::QPropertyBase::BindingBit)
+ return reinterpret_cast<QPropertyBindingPrivate*>(ptr->d_ptr & ~QtPrivate::QPropertyBase::FlagMask);
+ return nullptr;
+ }
- void setObservers(QPropertyObserver *observer);
+ void setObservers(QPropertyObserver *observer)
+ {
+ observer->prev = reinterpret_cast<QPropertyObserver**>(&(ptr->d_ptr));
+ ptr->d_ptr = (reinterpret_cast<quintptr>(observer) & ~QtPrivate::QPropertyBase::FlagMask);
+ }
void addObserver(QPropertyObserver *observer);
void setFirstObserver(QPropertyObserver *observer);
QPropertyObserverPointer firstObserver() const;
@@ -114,6 +129,150 @@ struct BindingEvaluationState
BindingEvaluationState **currentState = nullptr;
};
+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;
+ bool isBool = false;
+
+ QUntypedPropertyBinding::BindingEvaluationFunction evaluationFunction;
+
+ QPropertyObserverPointer firstObserver;
+ union {
+ ObserverArray inlineDependencyObservers;
+ struct {
+ void *staticObserver;
+ QtPrivate::QPropertyObserverCallback staticObserverCallback;
+ QtPrivate::QPropertyGuardFunction staticGuardCallback;
+ };
+ };
+ QScopedPointer<std::vector<QPropertyObserver>> heapObservers;
+
+ void *propertyDataPtr = nullptr;
+
+ QPropertyBindingSourceLocation location;
+ QPropertyBindingError error;
+
+ QMetaType metaType;
+
+public:
+ // public because the auto-tests access it, too.
+ size_t dependencyObserverCount = 0;
+
+ QPropertyBindingPrivate(const QMetaType &metaType, QUntypedPropertyBinding::BindingEvaluationFunction evaluationFunction,
+ const QPropertyBindingSourceLocation &location)
+ : isBool(metaType.id() == QMetaType::Bool)
+ , evaluationFunction(std::move(evaluationFunction))
+ , inlineDependencyObservers() // Explicit initialization required because of union
+ , location(location)
+ , metaType(metaType)
+ {}
+ virtual ~QPropertyBindingPrivate();
+
+ void setDirty(bool d) { dirty = d; }
+ void setProperty(void *propertyPtr) { propertyDataPtr = propertyPtr; }
+ void setStaticObserver(void *observer, QtPrivate::QPropertyObserverCallback callback,
+ QtPrivate::QPropertyGuardFunction guardCallback)
+ {
+ if (observer) {
+ if (!hasStaticObserver) {
+ if (dependencyObserverCount > 0) {
+ if (!heapObservers)
+ heapObservers.reset(new std::vector<QPropertyObserver>());
+ for (size_t 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;
+ staticGuardCallback = guardCallback;
+ } else if (hasStaticObserver) {
+ hasStaticObserver = false;
+ new (&inlineDependencyObservers) ObserverArray();
+ for (size_t 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;
+ }
+
+ QPropertyObserverPointer takeObservers()
+ {
+ auto observers = firstObserver;
+ firstObserver.ptr = nullptr;
+ return observers;
+ }
+
+ void clearDependencyObservers() {
+ if (!hasStaticObserver) {
+ for (size_t i = 0; i < qMin(dependencyObserverCount, inlineDependencyObservers.size()); ++i) {
+ QPropertyObserverPointer p{&inlineDependencyObservers[i]};
+ p.unlink();
+ }
+ }
+ if (heapObservers)
+ heapObservers->clear();
+ dependencyObserverCount = 0;
+ }
+ QPropertyObserverPointer allocateDependencyObserver() {
+ if (!hasStaticObserver && 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();
+ bool evaluateIfDirtyAndReturnTrueIfValueChanged();
+
+ static QPropertyBindingPrivate *get(const QUntypedPropertyBinding &binding)
+ { return binding.d.data(); }
+
+ void setError(QPropertyBindingError &&e)
+ { error = std::move(e); }
+
+ static QPropertyBindingPrivate *currentlyEvaluatingBinding();
+};
+
+inline void QPropertyBasePointer::setFirstObserver(QPropertyObserver *observer)
+{
+ if (auto *binding = bindingPtr()) {
+ binding->firstObserver.ptr = observer;
+ return;
+ }
+ ptr->d_ptr = reinterpret_cast<quintptr>(observer) | (ptr->d_ptr & QtPrivate::QPropertyBase::FlagMask);
+}
+
+inline QPropertyObserverPointer QPropertyBasePointer::firstObserver() const
+{
+ if (auto *binding = bindingPtr())
+ return binding->firstObserver;
+ return {reinterpret_cast<QPropertyObserver*>(ptr->d_ptr & ~QtPrivate::QPropertyBase::FlagMask)};
+}
+
QT_END_NAMESPACE
#endif // QPROPERTY_P_H
diff --git a/src/corelib/kernel/qpropertybinding.cpp b/src/corelib/kernel/qpropertybinding.cpp
deleted file mode 100644
index 63800c4f7d..0000000000
--- a/src/corelib/kernel/qpropertybinding.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qpropertybinding_p.h"
-#include "qproperty_p.h"
-
-#include <QScopedValueRollback>
-#include <QVariant>
-
-QT_BEGIN_NAMESPACE
-
-using namespace QtPrivate;
-
-QPropertyBindingPrivate::~QPropertyBindingPrivate()
-{
- if (firstObserver)
- firstObserver.unlink();
- if (!hasStaticObserver)
- inlineDependencyObservers.~ObserverArray(); // Explicit because of union.
-}
-
-void QPropertyBindingPrivate::unlinkAndDeref()
-{
- propertyDataPtr = nullptr;
- if (!ref.deref())
- delete this;
-}
-
-void QPropertyBindingPrivate::markDirtyAndNotifyObservers()
-{
- if (dirty)
- return;
- dirty = true;
- if (firstObserver)
- firstObserver.notify(this, propertyDataPtr);
- if (hasStaticObserver) {
- if (isBool) {
- auto propertyPtr = reinterpret_cast<QPropertyBase *>(propertyDataPtr);
- bool oldValue = propertyPtr->extraBit();
- staticObserverCallback(staticObserver, &oldValue);
- } else {
- staticObserverCallback(staticObserver, propertyDataPtr);
- }
- }
-}
-
-bool QPropertyBindingPrivate::evaluateIfDirtyAndReturnTrueIfValueChanged()
-{
- if (!dirty)
- return false;
-
- if (updating) {
- error = QPropertyBindingError(QPropertyBindingError::BindingLoop);
- return false;
- }
-
- /*
- * Evaluating the binding might lead to the binding being broken. This can
- * cause ref to reach zero at the end of the function. However, the
- * updateGuard's destructor will then still trigger, trying to set the
- * updating bool to its old value
- * To prevent this, we create a QPropertyBindingPrivatePtr which ensures
- * that the object is still alive when updateGuard's dtor runs.
- */
- QPropertyBindingPrivatePtr keepAlive {this};
- QScopedValueRollback<bool> updateGuard(updating, true);
-
- BindingEvaluationState evaluationFrame(this);
-
- bool changed = false;
-
- if (hasStaticObserver && staticGuardCallback) {
- if (isBool) {
- auto propertyPtr = reinterpret_cast<QPropertyBase *>(propertyDataPtr);
- bool newValue = propertyPtr->extraBit();
- changed = staticGuardCallback(metaType, &newValue, evaluationFunction, staticObserver);
- if (changed && !error.hasError())
- propertyPtr->setExtraBit(newValue);
- } else {
- changed = staticGuardCallback(metaType, propertyDataPtr, evaluationFunction, staticObserver);
- }
- } else {
- if (isBool) {
- auto propertyPtr = reinterpret_cast<QPropertyBase *>(propertyDataPtr);
- bool newValue = propertyPtr->extraBit();
- changed = evaluationFunction(metaType, &newValue);
- if (changed && !error.hasError())
- propertyPtr->setExtraBit(newValue);
- } else {
- changed = evaluationFunction(metaType, propertyDataPtr);
- }
- }
-
- dirty = false;
- return changed;
-}
-
-QUntypedPropertyBinding::QUntypedPropertyBinding() = default;
-
-QUntypedPropertyBinding::QUntypedPropertyBinding(const QMetaType &metaType, QUntypedPropertyBinding::BindingEvaluationFunction function,
- const QPropertyBindingSourceLocation &location)
-{
- d = new QPropertyBindingPrivate(metaType, std::move(function), std::move(location));
-}
-
-QUntypedPropertyBinding::QUntypedPropertyBinding(QUntypedPropertyBinding &&other)
- : d(std::move(other.d))
-{
-}
-
-QUntypedPropertyBinding::QUntypedPropertyBinding(const QUntypedPropertyBinding &other)
- : d(other.d)
-{
-}
-
-QUntypedPropertyBinding &QUntypedPropertyBinding::operator=(const QUntypedPropertyBinding &other)
-{
- d = other.d;
- return *this;
-}
-
-QUntypedPropertyBinding &QUntypedPropertyBinding::operator=(QUntypedPropertyBinding &&other)
-{
- d = std::move(other.d);
- return *this;
-}
-
-QUntypedPropertyBinding::QUntypedPropertyBinding(QPropertyBindingPrivate *priv)
- : d(priv)
-{
-}
-
-QUntypedPropertyBinding::~QUntypedPropertyBinding()
-{
-}
-
-bool QUntypedPropertyBinding::isNull() const
-{
- return !d;
-}
-
-QPropertyBindingError QUntypedPropertyBinding::error() const
-{
- if (!d)
- return QPropertyBindingError();
- return d->bindingError();
-}
-
-QMetaType QUntypedPropertyBinding::valueMetaType() const
-{
- if (!d)
- return QMetaType();
- return d->valueMetaType();
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qpropertybinding_p.h b/src/corelib/kernel/qpropertybinding_p.h
deleted file mode 100644
index 1aa2cd864c..0000000000
--- a/src/corelib/kernel/qpropertybinding_p.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPROPERTYBINDING_P_H
-#define QPROPERTYBINDING_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qshareddata.h>
-#include <QtCore/qscopedpointer.h>
-#include <vector>
-#include <functional>
-
-#include "qproperty_p.h"
-
-QT_BEGIN_NAMESPACE
-
-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;
- bool isBool = false;
-
- QUntypedPropertyBinding::BindingEvaluationFunction evaluationFunction;
-
- QPropertyObserverPointer firstObserver;
- union {
- ObserverArray inlineDependencyObservers;
- struct {
- void *staticObserver;
- QtPrivate::QPropertyObserverCallback staticObserverCallback;
- QtPrivate::QPropertyGuardFunction staticGuardCallback;
- };
- };
- QScopedPointer<std::vector<QPropertyObserver>> heapObservers;
-
- void *propertyDataPtr = nullptr;
-
- QPropertyBindingSourceLocation location;
- QPropertyBindingError error;
-
- QMetaType metaType;
-
-public:
- // public because the auto-tests access it, too.
- size_t dependencyObserverCount = 0;
-
- QPropertyBindingPrivate(const QMetaType &metaType, QUntypedPropertyBinding::BindingEvaluationFunction evaluationFunction,
- const QPropertyBindingSourceLocation &location)
- : isBool(metaType.id() == QMetaType::Bool)
- , evaluationFunction(std::move(evaluationFunction))
- , inlineDependencyObservers() // Explicit initialization required because of union
- , location(location)
- , metaType(metaType)
- {}
- virtual ~QPropertyBindingPrivate();
-
- void setDirty(bool d) { dirty = d; }
- void setProperty(void *propertyPtr) { propertyDataPtr = propertyPtr; }
- void setStaticObserver(void *observer, QtPrivate::QPropertyObserverCallback callback,
- QtPrivate::QPropertyGuardFunction guardCallback)
- {
- 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;
- staticGuardCallback = guardCallback;
- } 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;
- }
-
- QPropertyObserverPointer takeObservers()
- {
- auto observers = firstObserver;
- firstObserver.ptr = nullptr;
- return observers;
- }
-
- void clearDependencyObservers() {
- if (!hasStaticObserver) {
- for (size_t i = 0; i < qMin(dependencyObserverCount, inlineDependencyObservers.size()); ++i) {
- QPropertyObserverPointer p{&inlineDependencyObservers[i]};
- p.unlink();
- }
- }
- if (heapObservers)
- heapObservers->clear();
- dependencyObserverCount = 0;
- }
- QPropertyObserverPointer allocateDependencyObserver() {
- if (!hasStaticObserver && 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();
- bool evaluateIfDirtyAndReturnTrueIfValueChanged();
-
- static QPropertyBindingPrivate *get(const QUntypedPropertyBinding &binding)
- { return binding.d.data(); }
-
- void setError(QPropertyBindingError &&e)
- { error = std::move(e); }
-
- static QPropertyBindingPrivate *currentlyEvaluatingBinding();
-};
-
-QT_END_NAMESPACE
-
-#endif // QPROPERTYBINDING_P_H
diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h
index 91d9204996..ad5ed59e88 100644
--- a/src/corelib/kernel/qpropertyprivate.h
+++ b/src/corelib/kernel/qpropertyprivate.h
@@ -55,6 +55,8 @@
#include <QtCore/QExplicitlySharedDataPointer>
#include <QtCore/qtaggedpointer.h>
+#include <functional>
+
QT_BEGIN_NAMESPACE
class QUntypedPropertyBinding;