File indexing completed on 2025-09-16 09:04:37
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 #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
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
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