Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-07 08:48:20

0001 // Copyright (C) 2020 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QSHAREDDATA_H
0005 #define QSHAREDDATA_H
0006 
0007 #include <QtCore/qglobal.h>
0008 #include <QtCore/qatomic.h>
0009 #include <QtCore/qcompare.h>
0010 #include <QtCore/qhashfunctions.h>
0011 
0012 
0013 QT_BEGIN_NAMESPACE
0014 
0015 
0016 template <class T> class QSharedDataPointer;
0017 
0018 class QSharedData
0019 {
0020 public:
0021     mutable QAtomicInt ref;
0022 
0023     QSharedData() noexcept : ref(0) { }
0024     QSharedData(const QSharedData &) noexcept : ref(0) { }
0025 
0026     // using the assignment operator would lead to corruption in the ref-counting
0027     QSharedData &operator=(const QSharedData &) = delete;
0028     ~QSharedData() = default;
0029 };
0030 
0031 struct QAdoptSharedDataTag { explicit constexpr QAdoptSharedDataTag() = default; };
0032 
0033 template <typename T>
0034 class QSharedDataPointer
0035 {
0036 public:
0037     typedef T Type;
0038     typedef T *pointer;
0039 
0040     void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
0041     T &operator*() { detach(); return *(d.get()); }
0042     const T &operator*() const { return *(d.get()); }
0043     T *operator->() { detach(); return d.get(); }
0044     const T *operator->() const noexcept { return d.get(); }
0045     operator T *() { detach(); return d.get(); }
0046     operator const T *() const noexcept { return d.get(); }
0047     T *data() { detach(); return d.get(); }
0048     T *get() { detach(); return d.get(); }
0049     const T *data() const noexcept { return d.get(); }
0050     const T *get() const noexcept { return d.get(); }
0051     const T *constData() const noexcept { return d.get(); }
0052     T *take() noexcept { return std::exchange(d, nullptr).get(); }
0053 
0054     Q_NODISCARD_CTOR
0055     QSharedDataPointer() noexcept : d(nullptr) { }
0056     ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d.get(); }
0057 
0058     Q_NODISCARD_CTOR
0059     explicit QSharedDataPointer(T *data) noexcept : d(data)
0060     { if (d) d->ref.ref(); }
0061     Q_NODISCARD_CTOR
0062     QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
0063     {}
0064     Q_NODISCARD_CTOR
0065     QSharedDataPointer(const QSharedDataPointer &o) noexcept : d(o.d)
0066     { if (d) d->ref.ref(); }
0067 
0068     void reset(T *ptr = nullptr) noexcept
0069     {
0070         if (ptr != d.get()) {
0071             if (ptr)
0072                 ptr->ref.ref();
0073             T *old = std::exchange(d, Qt::totally_ordered_wrapper(ptr)).get();
0074             if (old && !old->ref.deref())
0075                 delete old;
0076         }
0077     }
0078 
0079     QSharedDataPointer &operator=(const QSharedDataPointer &o) noexcept
0080     {
0081         reset(o.d.get());
0082         return *this;
0083     }
0084     inline QSharedDataPointer &operator=(T *o) noexcept
0085     {
0086         reset(o);
0087         return *this;
0088     }
0089     Q_NODISCARD_CTOR
0090     QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(std::exchange(o.d, nullptr)) {}
0091     QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedDataPointer)
0092 
0093     operator bool () const noexcept { return d != nullptr; }
0094     bool operator!() const noexcept { return d == nullptr; }
0095 
0096     void swap(QSharedDataPointer &other) noexcept
0097     { qt_ptr_swap(d, other.d); }
0098 
0099 protected:
0100     T *clone();
0101 
0102 private:
0103     friend bool comparesEqual(const QSharedDataPointer &lhs, const QSharedDataPointer &rhs) noexcept
0104     { return lhs.d == rhs.d; }
0105     friend Qt::strong_ordering
0106     compareThreeWay(const QSharedDataPointer &lhs, const QSharedDataPointer &rhs) noexcept
0107     { return Qt::compareThreeWay(lhs.d, rhs.d); }
0108     Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer)
0109 
0110     friend bool comparesEqual(const QSharedDataPointer &lhs, const T *rhs) noexcept
0111     { return lhs.d == rhs; }
0112     friend Qt::strong_ordering
0113     compareThreeWay(const QSharedDataPointer &lhs, const T *rhs) noexcept
0114     { return Qt::compareThreeWay(lhs.d, rhs); }
0115     Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, T*)
0116 
0117     friend bool comparesEqual(const QSharedDataPointer &lhs, std::nullptr_t) noexcept
0118     { return lhs.d == nullptr; }
0119     friend Qt::strong_ordering
0120     compareThreeWay(const QSharedDataPointer &lhs, std::nullptr_t) noexcept
0121     { return Qt::compareThreeWay(lhs.d, nullptr); }
0122     Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, std::nullptr_t)
0123 
0124     void detach_helper();
0125 
0126     Qt::totally_ordered_wrapper<T *> d;
0127 };
0128 
0129 template <typename T>
0130 class QExplicitlySharedDataPointer
0131 {
0132 public:
0133     typedef T Type;
0134     typedef T *pointer;
0135 
0136     T &operator*() const { return *(d.get()); }
0137     T *operator->() noexcept { return d.get(); }
0138     T *operator->() const noexcept { return d.get(); }
0139     explicit operator T *() { return d.get(); }
0140     explicit operator const T *() const noexcept { return d.get(); }
0141     T *data() const noexcept { return d.get(); }
0142     T *get() const noexcept { return d.get(); }
0143     const T *constData() const noexcept { return d.get(); }
0144     T *take() noexcept { return std::exchange(d, nullptr).get(); }
0145 
0146     void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
0147 
0148     Q_NODISCARD_CTOR
0149     QExplicitlySharedDataPointer() noexcept : d(nullptr) { }
0150     ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d.get(); }
0151 
0152     Q_NODISCARD_CTOR
0153     explicit QExplicitlySharedDataPointer(T *data) noexcept : d(data)
0154     { if (d) d->ref.ref(); }
0155     Q_NODISCARD_CTOR
0156     QExplicitlySharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
0157     {}
0158     Q_NODISCARD_CTOR
0159     QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer &o) noexcept : d(o.d)
0160     { if (d) d->ref.ref(); }
0161 
0162     template<typename X>
0163     Q_NODISCARD_CTOR
0164     QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) noexcept
0165 #ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
0166 #error This macro has been removed in Qt 6.9.
0167 #endif
0168         : d(o.data())
0169     { if (d) d->ref.ref(); }
0170 
0171     void reset(T *ptr = nullptr) noexcept
0172     {
0173         if (ptr != d) {
0174             if (ptr)
0175                 ptr->ref.ref();
0176             T *old = std::exchange(d, Qt::totally_ordered_wrapper(ptr)).get();
0177             if (old && !old->ref.deref())
0178                 delete old;
0179         }
0180     }
0181 
0182     QExplicitlySharedDataPointer &operator=(const QExplicitlySharedDataPointer &o) noexcept
0183     {
0184         reset(o.d.get());
0185         return *this;
0186     }
0187     QExplicitlySharedDataPointer &operator=(T *o) noexcept
0188     {
0189         reset(o);
0190         return *this;
0191     }
0192     Q_NODISCARD_CTOR
0193     QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(std::exchange(o.d, nullptr)) {}
0194     QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QExplicitlySharedDataPointer)
0195 
0196     operator bool () const noexcept { return d != nullptr; }
0197     bool operator!() const noexcept { return d == nullptr; }
0198 
0199     void swap(QExplicitlySharedDataPointer &other) noexcept
0200     { qt_ptr_swap(d, other.d); }
0201 
0202 protected:
0203     T *clone();
0204 
0205 private:
0206     friend bool comparesEqual(const QExplicitlySharedDataPointer &lhs,
0207                               const QExplicitlySharedDataPointer &rhs) noexcept
0208     { return lhs.d == rhs.d; }
0209     friend Qt::strong_ordering
0210     compareThreeWay(const QExplicitlySharedDataPointer &lhs,
0211                     const QExplicitlySharedDataPointer &rhs) noexcept
0212     { return Qt::compareThreeWay(lhs.d, rhs.d); }
0213     Q_DECLARE_STRONGLY_ORDERED(QExplicitlySharedDataPointer)
0214 
0215     friend bool comparesEqual(const QExplicitlySharedDataPointer &lhs, const T *rhs) noexcept
0216     { return lhs.d == rhs; }
0217     friend Qt::strong_ordering
0218     compareThreeWay(const QExplicitlySharedDataPointer &lhs, const T *rhs) noexcept
0219     { return Qt::compareThreeWay(lhs.d, rhs); }
0220     Q_DECLARE_STRONGLY_ORDERED(QExplicitlySharedDataPointer, const T*)
0221 
0222     friend bool comparesEqual(const QExplicitlySharedDataPointer &lhs, std::nullptr_t) noexcept
0223     { return lhs.d == nullptr; }
0224     friend Qt::strong_ordering
0225     compareThreeWay(const QExplicitlySharedDataPointer &lhs, std::nullptr_t) noexcept
0226     { return Qt::compareThreeWay(lhs.d, nullptr); }
0227     Q_DECLARE_STRONGLY_ORDERED(QExplicitlySharedDataPointer, std::nullptr_t)
0228 
0229     void detach_helper();
0230 
0231     Qt::totally_ordered_wrapper<T *> d;
0232 };
0233 
0234 // Declared here and as Q_OUTOFLINE_TEMPLATE to work-around MSVC bug causing missing symbols at link time.
0235 template <typename T>
0236 Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
0237 {
0238     return new T(*d);
0239 }
0240 
0241 template <typename T>
0242 Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
0243 {
0244     T *x = clone();
0245     x->ref.ref();
0246     if (!d.get()->ref.deref())
0247         delete d.get();
0248     d.reset(x);
0249 }
0250 
0251 template <typename T>
0252 Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
0253 {
0254     return new T(*d.get());
0255 }
0256 
0257 template <typename T>
0258 Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
0259 {
0260     T *x = clone();
0261     x->ref.ref();
0262     if (!d->ref.deref())
0263         delete d.get();
0264     d.reset(x);
0265 }
0266 
0267 template <typename T>
0268 void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) noexcept
0269 { p1.swap(p2); }
0270 
0271 template <typename T>
0272 void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) noexcept
0273 { p1.swap(p2); }
0274 
0275 template <typename T>
0276 size_t qHash(const QSharedDataPointer<T> &ptr, size_t seed = 0) noexcept
0277 {
0278     return qHash(ptr.data(), seed);
0279 }
0280 template <typename T>
0281 size_t qHash(const QExplicitlySharedDataPointer<T> &ptr, size_t seed = 0) noexcept
0282 {
0283     return qHash(ptr.data(), seed);
0284 }
0285 
0286 template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_RELOCATABLE_TYPE);
0287 template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_RELOCATABLE_TYPE);
0288 
0289 #define QT_DECLARE_QSDP_SPECIALIZATION_DTOR(Class) \
0290     template<> QSharedDataPointer<Class>::~QSharedDataPointer();
0291 
0292 #define QT_DECLARE_QSDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro) \
0293     template<> ExportMacro QSharedDataPointer<Class>::~QSharedDataPointer();
0294 
0295 #define QT_DEFINE_QSDP_SPECIALIZATION_DTOR(Class) \
0296     template<> QSharedDataPointer<Class>::~QSharedDataPointer() \
0297     { \
0298         if (d && !d->ref.deref()) \
0299             delete d.get(); \
0300     }
0301 
0302 #define QT_DECLARE_QESDP_SPECIALIZATION_DTOR(Class) \
0303     template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
0304 
0305 #define QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro) \
0306     template<> ExportMacro QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
0307 
0308 #define QT_DEFINE_QESDP_SPECIALIZATION_DTOR(Class) \
0309     template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer() \
0310     { \
0311         if (d && !d->ref.deref()) \
0312             delete d.get(); \
0313     }
0314 
0315 QT_END_NAMESPACE
0316 
0317 #endif // QSHAREDDATA_H