summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qpropertyprivate.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qpropertyprivate.h')
-rw-r--r--src/corelib/kernel/qpropertyprivate.h108
1 files changed, 55 insertions, 53 deletions
diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h
index 5b6a9557f9..86dc08a6bc 100644
--- a/src/corelib/kernel/qpropertyprivate.h
+++ b/src/corelib/kernel/qpropertyprivate.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROPERTYPRIVATE_H
#define QPROPERTYPRIVATE_H
@@ -54,18 +18,31 @@
#include <QtCore/qglobal.h>
#include <QtCore/qtaggedpointer.h>
#include <QtCore/qmetatype.h>
+#include <QtCore/qcontainerfwd.h>
#include <functional>
QT_BEGIN_NAMESPACE
+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;}
};
}
@@ -88,7 +65,7 @@ public:
QPropertyBindingPrivatePtr() noexcept : d(nullptr) { }
~QPropertyBindingPrivatePtr()
{
- if (d && (--d->ref == 0))
+ if (d && !d->deref())
destroyAndFreeMemory();
}
Q_CORE_EXPORT void destroyAndFreeMemory();
@@ -109,14 +86,14 @@ 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; }
bool operator!() const noexcept { return d == nullptr; }
void swap(QPropertyBindingPrivatePtr &other) noexcept
- { qSwap(d, other.d); }
+ { qt_ptr_swap(d, other.d); }
friend bool operator==(const QPropertyBindingPrivatePtr &p1, const QPropertyBindingPrivatePtr &p2) noexcept
{ return p1.d == p2.d; }
@@ -146,14 +123,18 @@ private:
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;
@@ -178,6 +159,12 @@ struct QPropertyProxyBindingData
namespace QtPrivate {
struct BindingEvaluationState;
+/* used in BindingFunctionVTable::createFor; on all other compilers, void would work, but on
+ MSVC this causes C2182 when compiling in C++20 mode. As we only need to provide some default
+ value which gets ignored, we introduce this dummy type.
+*/
+struct MSVCWorkAround {};
+
struct BindingFunctionVTable
{
using CallFn = bool(*)(QMetaType, QUntypedPropertyData *, void *);
@@ -188,7 +175,7 @@ struct BindingFunctionVTable
const MoveCtrFn moveConstruct;
const qsizetype size;
- template<typename Callable, typename PropertyType=void>
+ template<typename Callable, typename PropertyType=MSVCWorkAround>
static constexpr BindingFunctionVTable createFor()
{
static_assert (alignof(Callable) <= alignof(std::max_align_t), "Bindings do not support overaligned functors!");
@@ -199,7 +186,7 @@ struct BindingFunctionVTable
static_assert (std::is_invocable_r_v<bool, Callable, QMetaType, QUntypedPropertyData *> );
auto untypedEvaluationFunction = static_cast<Callable *>(f);
return std::invoke(*untypedEvaluationFunction, metaType, dataPtr);
- } else if constexpr (!std::is_same_v<PropertyType, void>) { // check for void to woraround MSVC issue
+ } else if constexpr (!std::is_same_v<PropertyType, MSVCWorkAround>) {
Q_UNUSED(metaType);
QPropertyData<PropertyType> *propertyPtr = static_cast<QPropertyData<PropertyType> *>(dataPtr);
// That is allowed by POSIX even if Callable is a function pointer
@@ -213,8 +200,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(); },
@@ -226,7 +212,7 @@ struct BindingFunctionVTable
}
};
-template<typename Callable, typename PropertyType=void>
+template<typename Callable, typename PropertyType=MSVCWorkAround>
inline constexpr BindingFunctionVTable bindingFunctionVTable = BindingFunctionVTable::createFor<Callable, PropertyType>();
@@ -257,6 +243,10 @@ class Q_CORE_EXPORT QPropertyBindingData
friend struct QT_PREPEND_NAMESPACE(QPropertyBindingDataPointer);
friend class QT_PREPEND_NAMESPACE(QQmlPropertyBinding);
friend struct QT_PREPEND_NAMESPACE(QPropertyDelayedNotifications);
+
+ template<typename Class, typename T, auto Offset, auto Setter, auto Signal, auto Getter>
+ friend class QT_PREPEND_NAMESPACE(QObjectCompatProperty);
+
Q_DISABLE_COPY(QPropertyBindingData)
public:
QPropertyBindingData() = default;
@@ -302,13 +292,14 @@ public:
}
void registerWithCurrentlyEvaluatingBinding() const;
void notifyObservers(QUntypedPropertyData *propertyDataPtr) const;
+ void notifyObservers(QUntypedPropertyData *propertyDataPtr, QBindingStorage *storage) const;
private:
/*!
\internal
Returns a reference to d_ptr, except when d_ptr points to a proxy.
In that case, a reference to proxy->d_ptr is returned instead.
- To properly support proxying, direct access to d_ptr only occcurs when
+ To properly support proxying, direct access to d_ptr only occurs when
- a function actually deals with proxying (e.g.
QPropertyDelayedNotifications::addProperty),
- only the tag value is accessed (e.g. hasBinding) or
@@ -318,12 +309,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, QBindingStorage *storage,
+ QPropertyObserverPointer observer,
+ PendingBindingObserverList &bindingObservers) const;
};
template <typename T, typename Tag>