Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:36

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/qhashfunctions.h>
0010 
0011 #include <functional>
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; }
0042     const T &operator*() const { return *d; }
0043     T *operator->() { detach(); return d; }
0044     const T *operator->() const noexcept { return d; }
0045     operator T *() { detach(); return d; }
0046     operator const T *() const noexcept { return d; }
0047     T *data() { detach(); return d; }
0048     T *get() { detach(); return d; }
0049     const T *data() const noexcept { return d; }
0050     const T *get() const noexcept { return d; }
0051     const T *constData() const noexcept { return d; }
0052     T *take() noexcept { return std::exchange(d, nullptr); }
0053 
0054     Q_NODISCARD_CTOR
0055     QSharedDataPointer() noexcept : d(nullptr) { }
0056     ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
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) {
0071             if (ptr)
0072                 ptr->ref.ref();
0073             T *old = std::exchange(d, ptr);
0074             if (old && !old->ref.deref())
0075                 delete old;
0076         }
0077     }
0078 
0079     QSharedDataPointer &operator=(const QSharedDataPointer &o) noexcept
0080     {
0081         reset(o.d);
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 #define DECLARE_COMPARE_SET(T1, A1, T2, A2) \
0100     friend bool operator<(T1, T2) noexcept \
0101     { return std::less<T*>{}(A1, A2); } \
0102     friend bool operator<=(T1, T2) noexcept \
0103     { return !std::less<T*>{}(A2, A1); } \
0104     friend bool operator>(T1, T2) noexcept \
0105     { return std::less<T*>{}(A2, A1); } \
0106     friend bool operator>=(T1, T2) noexcept \
0107     { return !std::less<T*>{}(A1, A2); } \
0108     friend bool operator==(T1, T2) noexcept \
0109     { return A1 == A2; } \
0110     friend bool operator!=(T1, T2) noexcept \
0111     { return A1 != A2; } \
0112 
0113     DECLARE_COMPARE_SET(const QSharedDataPointer &p1, p1.d, const QSharedDataPointer &p2, p2.d)
0114     DECLARE_COMPARE_SET(const QSharedDataPointer &p1, p1.d, const T *ptr, ptr)
0115     DECLARE_COMPARE_SET(const T *ptr, ptr, const QSharedDataPointer &p2, p2.d)
0116     DECLARE_COMPARE_SET(const QSharedDataPointer &p1, p1.d, std::nullptr_t, nullptr)
0117     DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QSharedDataPointer &p2, p2.d)
0118 
0119 protected:
0120     T *clone();
0121 
0122 private:
0123     void detach_helper();
0124 
0125     T *d;
0126 };
0127 
0128 template <typename T>
0129 class QExplicitlySharedDataPointer
0130 {
0131 public:
0132     typedef T Type;
0133     typedef T *pointer;
0134 
0135     T &operator*() const { return *d; }
0136     T *operator->() noexcept { return d; }
0137     T *operator->() const noexcept { return d; }
0138     explicit operator T *() { return d; }
0139     explicit operator const T *() const noexcept { return d; }
0140     T *data() const noexcept { return d; }
0141     T *get() const noexcept { return d; }
0142     const T *constData() const noexcept { return d; }
0143     T *take() noexcept { return std::exchange(d, nullptr); }
0144 
0145     void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
0146 
0147     Q_NODISCARD_CTOR
0148     QExplicitlySharedDataPointer() noexcept : d(nullptr) { }
0149     ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; }
0150 
0151     Q_NODISCARD_CTOR
0152     explicit QExplicitlySharedDataPointer(T *data) noexcept : d(data)
0153     { if (d) d->ref.ref(); }
0154     Q_NODISCARD_CTOR
0155     QExplicitlySharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
0156     {}
0157     Q_NODISCARD_CTOR
0158     QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer &o) noexcept : d(o.d)
0159     { if (d) d->ref.ref(); }
0160 
0161     template<typename X>
0162     Q_NODISCARD_CTOR
0163     QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) noexcept
0164 #ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
0165         : d(static_cast<T *>(o.data()))
0166 #else
0167         : d(o.data())
0168 #endif
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, ptr);
0177             if (old && !old->ref.deref())
0178                 delete old;
0179         }
0180     }
0181 
0182     QExplicitlySharedDataPointer &operator=(const QExplicitlySharedDataPointer &o) noexcept
0183     {
0184         reset(o.d);
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     DECLARE_COMPARE_SET(const QExplicitlySharedDataPointer &p1, p1.d, const QExplicitlySharedDataPointer &p2, p2.d)
0203     DECLARE_COMPARE_SET(const QExplicitlySharedDataPointer &p1, p1.d, const T *ptr, ptr)
0204     DECLARE_COMPARE_SET(const T *ptr, ptr, const QExplicitlySharedDataPointer &p2, p2.d)
0205     DECLARE_COMPARE_SET(const QExplicitlySharedDataPointer &p1, p1.d, std::nullptr_t, nullptr)
0206     DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QExplicitlySharedDataPointer &p2, p2.d)
0207 
0208 #undef DECLARE_COMPARE_SET
0209 
0210 protected:
0211     T *clone();
0212 
0213 private:
0214     void detach_helper();
0215 
0216     T *d;
0217 };
0218 
0219 // Declared here and as Q_OUTOFLINE_TEMPLATE to work-around MSVC bug causing missing symbols at link time.
0220 template <typename T>
0221 Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
0222 {
0223     return new T(*d);
0224 }
0225 
0226 template <typename T>
0227 Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
0228 {
0229     T *x = clone();
0230     x->ref.ref();
0231     if (!d->ref.deref())
0232         delete d;
0233     d = x;
0234 }
0235 
0236 template <typename T>
0237 Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
0238 {
0239     return new T(*d);
0240 }
0241 
0242 template <typename T>
0243 Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
0244 {
0245     T *x = clone();
0246     x->ref.ref();
0247     if (!d->ref.deref())
0248         delete d;
0249     d = x;
0250 }
0251 
0252 template <typename T>
0253 void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) noexcept
0254 { p1.swap(p2); }
0255 
0256 template <typename T>
0257 void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) noexcept
0258 { p1.swap(p2); }
0259 
0260 template <typename T>
0261 size_t qHash(const QSharedDataPointer<T> &ptr, size_t seed = 0) noexcept
0262 {
0263     return qHash(ptr.data(), seed);
0264 }
0265 template <typename T>
0266 size_t qHash(const QExplicitlySharedDataPointer<T> &ptr, size_t seed = 0) noexcept
0267 {
0268     return qHash(ptr.data(), seed);
0269 }
0270 
0271 template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_RELOCATABLE_TYPE);
0272 template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_RELOCATABLE_TYPE);
0273 
0274 #define QT_DECLARE_QSDP_SPECIALIZATION_DTOR(Class) \
0275     template<> QSharedDataPointer<Class>::~QSharedDataPointer();
0276 
0277 #define QT_DECLARE_QSDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro) \
0278     template<> ExportMacro QSharedDataPointer<Class>::~QSharedDataPointer();
0279 
0280 #define QT_DEFINE_QSDP_SPECIALIZATION_DTOR(Class) \
0281     template<> QSharedDataPointer<Class>::~QSharedDataPointer() \
0282     { \
0283         if (d && !d->ref.deref()) \
0284             delete d; \
0285     }
0286 
0287 #define QT_DECLARE_QESDP_SPECIALIZATION_DTOR(Class) \
0288     template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
0289 
0290 #define QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro) \
0291     template<> ExportMacro QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
0292 
0293 #define QT_DEFINE_QESDP_SPECIALIZATION_DTOR(Class) \
0294     template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer() \
0295     { \
0296         if (d && !d->ref.deref()) \
0297             delete d; \
0298     }
0299 
0300 QT_END_NAMESPACE
0301 
0302 #endif // QSHAREDDATA_H