diff options
Diffstat (limited to 'src/corelib/tools/qsharedpointer_impl.h')
-rw-r--r-- | src/corelib/tools/qsharedpointer_impl.h | 173 |
1 files changed, 113 insertions, 60 deletions
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 0e69c18ca4..456be91d03 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Copyright (C) 2020 Intel Corporation. -** Copyright (C) 2019 Klarälvdalens Datakonsult AB. -** 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) 2021 The Qt Company Ltd. +// Copyright (C) 2022 Intel Corporation. +// Copyright (C) 2019 Klarälvdalens Datakonsult AB. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef Q_QDOC @@ -62,13 +26,18 @@ QT_END_NAMESPACE #include <new> #include <QtCore/qatomic.h> -#include <QtCore/qobject.h> // for qobject_cast #include <QtCore/qhashfunctions.h> +#include <QtCore/qmetatype.h> // for IsPointerToTypeDerivedFromQObject +#include <QtCore/qxptype_traits.h> #include <memory> QT_BEGIN_NAMESPACE +class QObject; +template <class T> +T qobject_cast(const QObject *object); + // // forward declarations // @@ -147,8 +116,10 @@ namespace QtSharedPointer { #ifndef QT_NO_QOBJECT Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *); + QT6_ONLY( Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable); - Q_CORE_EXPORT void checkQObjectShared(const QObject *); + ) + QT6_ONLY(Q_CORE_EXPORT void checkQObjectShared(const QObject *);) #endif inline void checkQObjectShared(...) { } inline void setQObjectShared(...) { } @@ -308,23 +279,29 @@ public: T &operator*() const { return *data(); } T *operator->() const noexcept { return data(); } + Q_NODISCARD_CTOR constexpr QSharedPointer() noexcept : value(nullptr), d(nullptr) { } ~QSharedPointer() { deref(); } + Q_NODISCARD_CTOR constexpr QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { } template <class X, IfCompatible<X> = true> + Q_NODISCARD_CTOR inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept { internalConstruct(ptr, QtSharedPointer::NormalDeleter()); } template <class X, typename Deleter, IfCompatible<X> = true> + Q_NODISCARD_CTOR inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws { internalConstruct(ptr, deleter); } template <typename Deleter> + Q_NODISCARD_CTOR QSharedPointer(std::nullptr_t, Deleter deleter) : value(nullptr) { internalConstruct(static_cast<T *>(nullptr), deleter); } + Q_NODISCARD_CTOR QSharedPointer(const QSharedPointer &other) noexcept : value(other.value), d(other.d) { if (d) ref(); } QSharedPointer &operator=(const QSharedPointer &other) noexcept @@ -333,6 +310,7 @@ public: swap(copy); return *this; } + Q_NODISCARD_CTOR QSharedPointer(QSharedPointer &&other) noexcept : value(other.value), d(other.d) { @@ -342,6 +320,7 @@ public: QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedPointer) template <class X, IfCompatible<X> = true> + Q_NODISCARD_CTOR QSharedPointer(QSharedPointer<X> &&other) noexcept : value(other.value), d(other.d) { @@ -358,6 +337,7 @@ public: } template <class X, IfCompatible<X> = true> + Q_NODISCARD_CTOR QSharedPointer(const QSharedPointer<X> &other) noexcept : value(other.value), d(other.d) { if (d) ref(); } @@ -370,6 +350,7 @@ public: } template <class X, IfCompatible<X> = true> + Q_NODISCARD_CTOR inline QSharedPointer(const QWeakPointer<X> &other) : value(nullptr), d(nullptr) { *this = other; } @@ -415,10 +396,10 @@ public: inline void clear() { QSharedPointer copy; swap(copy); } - QWeakPointer<T> toWeakRef() const; + [[nodiscard]] QWeakPointer<T> toWeakRef() const; template <typename... Args> - static QSharedPointer create(Args && ...arguments) + [[nodiscard]] static QSharedPointer create(Args && ...arguments) { typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private; # ifdef QT_SHAREDPOINTER_TRACK_POINTERS @@ -465,7 +446,25 @@ public: #undef DECLARE_TEMPLATE_COMPARE_SET #undef DECLARE_COMPARE_SET + template <typename X> + bool owner_before(const QSharedPointer<X> &other) const noexcept + { return std::less<>()(d, other.d); } + template <typename X> + bool owner_before(const QWeakPointer<X> &other) const noexcept + { return std::less<>()(d, other.d); } + + template <typename X> + bool owner_equal(const QSharedPointer<X> &other) const noexcept + { return d == other.d; } + template <typename X> + bool owner_equal(const QWeakPointer<X> &other) const noexcept + { return d == other.d; } + + size_t owner_hash() const noexcept + { return std::hash<Data *>()(d); } + private: + Q_NODISCARD_CTOR explicit QSharedPointer(Qt::Initialization) {} void deref() noexcept @@ -502,14 +501,13 @@ private: #ifdef QT_SHAREDPOINTER_TRACK_POINTERS internalSafetyCheckAdd(d, ptr); #endif - d->setQObjectShared(ptr, true); enableSharedFromThis(ptr); } void internalSwap(QSharedPointer &other) noexcept { - qSwap(d, other.d); - qSwap(this->value, other.value); + qt_ptr_swap(d, other.d); + qt_ptr_swap(this->value, other.value); } template <class X> friend class QSharedPointer; @@ -530,16 +528,14 @@ private: tmp = o->strongref.loadRelaxed(); // failed, try again } - if (tmp > 0) { + if (tmp > 0) o->weakref.ref(); - } else { - o->checkQObjectShared(actual); + else o = nullptr; - } } - qSwap(d, o); - qSwap(this->value, actual); + qt_ptr_swap(d, o); + qt_ptr_swap(this->value, actual); if (!d || d->strongref.loadRelaxed() == 0) this->value = nullptr; @@ -558,6 +554,12 @@ class QWeakPointer template <typename X> using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type; + template <typename X> + using IfVirtualBase = typename std::enable_if<qxp::is_virtual_base_of_v<T, X>, bool>::type; + + template <typename X> + using IfNotVirtualBase = typename std::enable_if<!qxp::is_virtual_base_of_v<T, X>, bool>::type; + public: typedef T element_type; typedef T value_type; @@ -571,11 +573,14 @@ public: explicit operator bool() const noexcept { return !isNull(); } bool operator !() const noexcept { return isNull(); } - inline QWeakPointer() noexcept : d(nullptr), value(nullptr) { } + Q_NODISCARD_CTOR + constexpr QWeakPointer() noexcept : d(nullptr), value(nullptr) { } inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; } + Q_NODISCARD_CTOR QWeakPointer(const QWeakPointer &other) noexcept : d(other.d), value(other.value) { if (d) d->weakref.ref(); } + Q_NODISCARD_CTOR QWeakPointer(QWeakPointer &&other) noexcept : d(other.d), value(other.value) { @@ -583,6 +588,32 @@ public: other.value = nullptr; } QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QWeakPointer) + + template <class X, IfCompatible<X> = true, IfNotVirtualBase<X> = true> + Q_NODISCARD_CTOR + QWeakPointer(QWeakPointer<X> &&other) noexcept + : d(std::exchange(other.d, nullptr)), + value(std::exchange(other.value, nullptr)) + { + } + + template <class X, IfCompatible<X> = true, IfVirtualBase<X> = true> + Q_NODISCARD_CTOR + QWeakPointer(QWeakPointer<X> &&other) noexcept + : d(other.d), value(other.toStrongRef().get()) // must go through QSharedPointer, see below + { + other.d = nullptr; + other.value = nullptr; + } + + template <class X, IfCompatible<X> = true> + QWeakPointer &operator=(QWeakPointer<X> &&other) noexcept + { + QWeakPointer moved(std::move(other)); + swap(moved); + return *this; + } + QWeakPointer &operator=(const QWeakPointer &other) noexcept { QWeakPointer copy(other); @@ -592,10 +623,11 @@ public: void swap(QWeakPointer &other) noexcept { - qSwap(this->d, other.d); - qSwap(this->value, other.value); + qt_ptr_swap(this->d, other.d); + qt_ptr_swap(this->value, other.value); } + Q_NODISCARD_CTOR inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data()) { if (d) d->weakref.ref();} inline QWeakPointer &operator=(const QSharedPointer<T> &o) @@ -605,6 +637,7 @@ public: } template <class X, IfCompatible<X> = true> + Q_NODISCARD_CTOR inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr) { *this = o; } @@ -618,6 +651,7 @@ public: } template <class X, IfCompatible<X> = true> + Q_NODISCARD_CTOR inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr) { *this = o; } @@ -630,9 +664,9 @@ public: inline void clear() { *this = QWeakPointer(); } - inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); } + [[nodiscard]] QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); } // std::weak_ptr compatibility: - inline QSharedPointer<T> lock() const { return toStrongRef(); } + [[nodiscard]] QSharedPointer<T> lock() const { return toStrongRef(); } template <class X> bool operator==(const QWeakPointer<X> &o) const noexcept @@ -666,17 +700,36 @@ public: friend bool operator!=(std::nullptr_t, const QWeakPointer &p) { return !p.isNull(); } + template <typename X> + bool owner_before(const QWeakPointer<X> &other) const noexcept + { return std::less<>()(d, other.d); } + template <typename X> + bool owner_before(const QSharedPointer<X> &other) const noexcept + { return std::less<>()(d, other.d); } + + template <typename X> + bool owner_equal(const QWeakPointer<X> &other) const noexcept + { return d == other.d; } + template <typename X> + bool owner_equal(const QSharedPointer<X> &other) const noexcept + { return d == other.d; } + + size_t owner_hash() const noexcept + { return std::hash<Data *>()(d); } + private: friend struct QtPrivate::EnableInternalData; template <class X> friend class QSharedPointer; + template <class X> friend class QWeakPointer; template <class X> friend class QPointer; template <class X> inline QWeakPointer &assign(X *ptr) - { return *this = QWeakPointer<X>(ptr, true); } + { return *this = QWeakPointer<T>(ptr, true); } #ifndef QT_NO_QOBJECT template <class X, IfCompatible<X> = true> + Q_NODISCARD_CTOR inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr) { } #endif @@ -784,7 +837,7 @@ Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2) template <class T> Q_INLINE_TEMPLATE size_t qHash(const QSharedPointer<T> &ptr, size_t seed = 0) { - return QT_PREPEND_NAMESPACE(qHash)(ptr.data(), seed); + return qHash(ptr.data(), seed); } |