File indexing completed on 2026-05-07 08:48:20
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/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
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
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