Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 09:04:37

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