diff options
Diffstat (limited to 'src/corelib/kernel/qpropertyprivate.h')
-rw-r--r-- | src/corelib/kernel/qpropertyprivate.h | 105 |
1 files changed, 52 insertions, 53 deletions
diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h index 2fa82f6342..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,6 +18,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qtaggedpointer.h> #include <QtCore/qmetatype.h> +#include <QtCore/qcontainerfwd.h> #include <functional> @@ -61,13 +26,23 @@ 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;} }; } @@ -90,7 +65,7 @@ public: QPropertyBindingPrivatePtr() noexcept : d(nullptr) { } ~QPropertyBindingPrivatePtr() { - if (d && (--d->ref == 0)) + if (d && !d->deref()) destroyAndFreeMemory(); } Q_CORE_EXPORT void destroyAndFreeMemory(); @@ -111,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; } @@ -148,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; @@ -180,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 *); @@ -190,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!"); @@ -201,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 @@ -215,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(); }, @@ -228,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>(); @@ -259,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; @@ -311,7 +299,7 @@ private: 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 @@ -321,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> |