File indexing completed on 2025-01-18 10:07:36
0001
0002
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
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
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