Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:09:31

0001 // Copyright (C) 2021 The Qt Company Ltd.
0002 // Copyright (C) 2022 Intel Corporation.
0003 // Copyright (C) 2019 Klarälvdalens Datakonsult AB.
0004 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0005 
0006 #ifndef Q_QDOC
0007 
0008 #ifndef QSHAREDPOINTER_H
0009 #error Do not include qsharedpointer_impl.h directly
0010 #endif
0011 
0012 #if 0
0013 #pragma qt_sync_skip_header_check
0014 #pragma qt_sync_stop_processing
0015 #endif
0016 
0017 #if 0
0018 // These macros are duplicated here to make syncqt not complain a about
0019 // this header, as we have a "qt_sync_stop_processing" below, which in turn
0020 // is here because this file contains a template mess and duplicates the
0021 // classes found in qsharedpointer.h
0022 QT_BEGIN_NAMESPACE
0023 QT_END_NAMESPACE
0024 #pragma qt_sync_stop_processing
0025 #endif
0026 
0027 #include <new>
0028 #include <QtCore/qatomic.h>
0029 #include <QtCore/qhashfunctions.h>
0030 #include <QtCore/qmetatype.h> // for IsPointerToTypeDerivedFromQObject
0031 #include <QtCore/qxptype_traits.h>
0032 
0033 #include <memory>
0034 
0035 QT_BEGIN_NAMESPACE
0036 
0037 class QObject;
0038 template <class T>
0039 T qobject_cast(const QObject *object);
0040 
0041 //
0042 // forward declarations
0043 //
0044 template <class T> class QWeakPointer;
0045 template <class T> class QSharedPointer;
0046 template <class T> class QEnableSharedFromThis;
0047 
0048 class QVariant;
0049 
0050 template <class X, class T>
0051 QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr);
0052 template <class X, class T>
0053 QSharedPointer<X> qSharedPointerCast(QSharedPointer<T> &&ptr);
0054 template <class X, class T>
0055 QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
0056 template <class X, class T>
0057 QSharedPointer<X> qSharedPointerDynamicCast(QSharedPointer<T> &&ptr);
0058 template <class X, class T>
0059 QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
0060 template <class X, class T>
0061 QSharedPointer<X> qSharedPointerConstCast(QSharedPointer<T> &&ptr);
0062 
0063 #ifndef QT_NO_QOBJECT
0064 template <class X, class T>
0065 QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
0066 template <class X, class T>
0067 QSharedPointer<X> qSharedPointerObjectCast(QSharedPointer<T> &&ptr);
0068 #endif
0069 
0070 namespace QtPrivate {
0071 struct EnableInternalData;
0072 }
0073 
0074 namespace QtSharedPointer {
0075     template <class T> class ExternalRefCount;
0076 
0077     template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
0078     template <class X, class Y> QSharedPointer<X> movePointer(X * ptr, QSharedPointer<Y> &&src);
0079 
0080     // used in debug mode to verify the reuse of pointers
0081     Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *);
0082     Q_CORE_EXPORT void internalSafetyCheckRemove(const void *);
0083 
0084     template <class T, typename Klass, typename RetVal>
0085     inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
0086     { if (t) (t->*memberDeleter)(); }
0087     template <class T, typename Deleter>
0088     inline void executeDeleter(T *t, Deleter d)
0089     { d(t); }
0090     struct NormalDeleter {};
0091 
0092     // this uses partial template specialization
0093     template <class T> struct RemovePointer;
0094     template <class T> struct RemovePointer<T *> { typedef T Type; };
0095     template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
0096     template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
0097 
0098     // This class is the d-pointer of QSharedPointer and QWeakPointer.
0099     //
0100     // It is a reference-counted reference counter. "strongref" is the inner
0101     // reference counter, and it tracks the lifetime of the pointer itself.
0102     // "weakref" is the outer reference counter and it tracks the lifetime of
0103     // the ExternalRefCountData object.
0104     //
0105     // The deleter is stored in the destroyer member and is always a pointer to
0106     // a static function in ExternalRefCountWithCustomDeleter or in
0107     // ExternalRefCountWithContiguousData
0108     struct ExternalRefCountData
0109     {
0110         typedef void (*DestroyerFn)(ExternalRefCountData *);
0111         QBasicAtomicInt weakref;
0112         QBasicAtomicInt strongref;
0113         DestroyerFn destroyer;
0114 
0115         inline ExternalRefCountData(DestroyerFn d)
0116             : destroyer(d)
0117         {
0118             strongref.storeRelaxed(1);
0119             weakref.storeRelaxed(1);
0120         }
0121         inline ExternalRefCountData(Qt::Initialization) { }
0122         ~ExternalRefCountData() { Q_ASSERT(!weakref.loadRelaxed()); Q_ASSERT(strongref.loadRelaxed() <= 0); }
0123 
0124         void destroy() { destroyer(this); }
0125 
0126 #ifndef QT_NO_QOBJECT
0127         Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
0128         QT6_ONLY(
0129         Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
0130         )
0131         QT6_ONLY(Q_CORE_EXPORT void checkQObjectShared(const QObject *);)
0132 #endif
0133         inline void checkQObjectShared(...) { }
0134         inline void setQObjectShared(...) { }
0135 
0136         // Normally, only subclasses of ExternalRefCountData are allocated
0137         // One exception exists in getAndRef; that uses the global operator new
0138         // to prevent a mismatch with the custom operator delete
0139         inline void *operator new(std::size_t) = delete;
0140         // placement new
0141         inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
0142         inline void operator delete(void *ptr) { ::operator delete(ptr); }
0143         inline void operator delete(void *, void *) { }
0144     };
0145     // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit)
0146 
0147     template <class T, typename Deleter>
0148     struct CustomDeleter
0149     {
0150         Deleter deleter;
0151         T *ptr;
0152 
0153         CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
0154         void execute() { executeDeleter(ptr, deleter); }
0155     };
0156     // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding
0157     // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding
0158     // for Deleter = function pointer:  8 (32-bit) / 16 (64-bit)
0159     // for Deleter = PMF: 12 (32-bit) / 24 (64-bit)  (GCC)
0160 
0161     // This specialization of CustomDeleter for a deleter of type NormalDeleter
0162     // is an optimization: instead of storing a pointer to a function that does
0163     // the deleting, we simply delete the pointer ourselves.
0164     template <class T>
0165     struct CustomDeleter<T, NormalDeleter>
0166     {
0167         T *ptr;
0168 
0169         CustomDeleter(T *p, NormalDeleter) : ptr(p) {}
0170         void execute() { delete ptr; }
0171     };
0172     // sizeof(CustomDeleter specialization) = sizeof(void*)
0173 
0174     // This class extends ExternalRefCountData and implements
0175     // the static function that deletes the object. The pointer and the
0176     // custom deleter are kept in the "extra" member so we can construct
0177     // and destruct it independently of the full structure.
0178     template <class T, typename Deleter>
0179     struct ExternalRefCountWithCustomDeleter: public ExternalRefCountData
0180     {
0181         typedef ExternalRefCountWithCustomDeleter Self;
0182         typedef ExternalRefCountData BaseClass;
0183         CustomDeleter<T, Deleter> extra;
0184 
0185         static inline void deleter(ExternalRefCountData *self)
0186         {
0187             Self *realself = static_cast<Self *>(self);
0188             realself->extra.execute();
0189 
0190             // delete the deleter too
0191             realself->extra.~CustomDeleter<T, Deleter>();
0192         }
0193         static void safetyCheckDeleter(ExternalRefCountData *self)
0194         {
0195             internalSafetyCheckRemove(self);
0196             deleter(self);
0197         }
0198 
0199         static inline Self *create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
0200         {
0201             Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
0202 
0203             // initialize the two sub-objects
0204             new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter);
0205             new (d) BaseClass(actualDeleter); // can't throw
0206 
0207             return d;
0208         }
0209     private:
0210         // prevent construction
0211         ExternalRefCountWithCustomDeleter() = delete;
0212         ~ExternalRefCountWithCustomDeleter() = delete;
0213         Q_DISABLE_COPY(ExternalRefCountWithCustomDeleter)
0214     };
0215 
0216     // This class extends ExternalRefCountData and adds a "T"
0217     // member. That way, when the create() function is called, we allocate
0218     // memory for both QSharedPointer's d-pointer and the actual object being
0219     // tracked.
0220     template <class T>
0221     struct ExternalRefCountWithContiguousData: public ExternalRefCountData
0222     {
0223         typedef ExternalRefCountData Parent;
0224         typedef typename std::remove_cv<T>::type NoCVType;
0225         NoCVType data;
0226 
0227         static void deleter(ExternalRefCountData *self)
0228         {
0229             ExternalRefCountWithContiguousData *that =
0230                     static_cast<ExternalRefCountWithContiguousData *>(self);
0231             that->data.~T();
0232             Q_UNUSED(that); // MSVC warns if T has a trivial destructor
0233         }
0234         static void safetyCheckDeleter(ExternalRefCountData *self)
0235         {
0236             internalSafetyCheckRemove(self);
0237             deleter(self);
0238         }
0239         static void noDeleter(ExternalRefCountData *) { }
0240 
0241         static inline ExternalRefCountData *create(NoCVType **ptr, DestroyerFn destroy)
0242         {
0243             ExternalRefCountWithContiguousData *d =
0244                 static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
0245 
0246             // initialize the d-pointer sub-object
0247             // leave d->data uninitialized
0248             new (d) Parent(destroy); // can't throw
0249 
0250             *ptr = &d->data;
0251             return d;
0252         }
0253 
0254     private:
0255         // prevent construction
0256         ExternalRefCountWithContiguousData() = delete;
0257         ~ExternalRefCountWithContiguousData() = delete;
0258         Q_DISABLE_COPY(ExternalRefCountWithContiguousData)
0259     };
0260 
0261 #ifndef QT_NO_QOBJECT
0262     Q_CORE_EXPORT QWeakPointer<QObject> weakPointerFromVariant_internal(const QVariant &variant);
0263     Q_CORE_EXPORT QSharedPointer<QObject> sharedPointerFromVariant_internal(const QVariant &variant);
0264 #endif
0265 } // namespace QtSharedPointer
0266 
0267 template <class T> class QSharedPointer
0268 {
0269     typedef QtSharedPointer::ExternalRefCountData Data;
0270     template <typename X>
0271     using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
0272 
0273 public:
0274     typedef T Type;
0275     typedef T element_type;
0276     typedef T value_type;
0277     typedef value_type *pointer;
0278     typedef const value_type *const_pointer;
0279     typedef value_type &reference;
0280     typedef const value_type &const_reference;
0281     typedef qptrdiff difference_type;
0282 
0283     T *data() const noexcept { return value.get(); }
0284     T *get() const noexcept { return value.get(); }
0285     bool isNull() const noexcept { return !data(); }
0286     explicit operator bool() const noexcept { return !isNull(); }
0287     bool operator !() const noexcept { return isNull(); }
0288     T &operator*() const { return *data(); }
0289     T *operator->() const noexcept { return data(); }
0290 
0291     Q_NODISCARD_CTOR
0292     constexpr QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
0293     ~QSharedPointer() { deref(); }
0294 
0295     Q_NODISCARD_CTOR
0296     constexpr QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
0297 
0298     template <class X, IfCompatible<X> = true>
0299     Q_NODISCARD_CTOR
0300     inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
0301     { internalConstruct(ptr, QtSharedPointer::NormalDeleter()); }
0302 
0303     template <class X, typename Deleter, IfCompatible<X> = true>
0304     Q_NODISCARD_CTOR
0305     inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws
0306     { internalConstruct(ptr, deleter); }
0307 
0308     template <typename Deleter>
0309     Q_NODISCARD_CTOR
0310     QSharedPointer(std::nullptr_t, Deleter deleter) : value(nullptr)
0311     { internalConstruct(static_cast<T *>(nullptr), deleter); }
0312 
0313     Q_NODISCARD_CTOR
0314     QSharedPointer(const QSharedPointer &other) noexcept : value(other.value.get()), d(other.d)
0315     { if (d) ref(); }
0316     QSharedPointer &operator=(const QSharedPointer &other) noexcept
0317     {
0318         QSharedPointer copy(other);
0319         swap(copy);
0320         return *this;
0321     }
0322     Q_NODISCARD_CTOR
0323     QSharedPointer(QSharedPointer &&other) noexcept
0324         : value(other.value.get()), d(other.d)
0325     {
0326         other.d = nullptr;
0327         other.value = nullptr;
0328     }
0329     QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedPointer)
0330 
0331     template <class X, IfCompatible<X> = true>
0332     Q_NODISCARD_CTOR
0333     QSharedPointer(QSharedPointer<X> &&other) noexcept
0334         : value(other.value.get()), d(other.d)
0335     {
0336         other.d = nullptr;
0337         other.value = nullptr;
0338     }
0339 
0340     template <class X, IfCompatible<X> = true>
0341     QSharedPointer &operator=(QSharedPointer<X> &&other) noexcept
0342     {
0343         QSharedPointer moved(std::move(other));
0344         swap(moved);
0345         return *this;
0346     }
0347 
0348     template <class X, IfCompatible<X> = true>
0349     Q_NODISCARD_CTOR
0350     QSharedPointer(const QSharedPointer<X> &other) noexcept : value(other.value.get()), d(other.d)
0351     { if (d) ref(); }
0352 
0353     template <class X, IfCompatible<X> = true>
0354     inline QSharedPointer &operator=(const QSharedPointer<X> &other)
0355     {
0356         QSharedPointer copy(other);
0357         swap(copy);
0358         return *this;
0359     }
0360 
0361     template <class X, IfCompatible<X> = true>
0362     Q_NODISCARD_CTOR
0363     inline QSharedPointer(const QWeakPointer<X> &other) : value(nullptr), d(nullptr)
0364     { *this = other; }
0365 
0366     template <class X, IfCompatible<X> = true>
0367     inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
0368     { internalSet(other.d, other.value); return *this; }
0369 
0370     inline void swap(QSharedPointer &other) noexcept
0371     { this->internalSwap(other); }
0372 
0373     inline void reset() { clear(); }
0374     inline void reset(T *t)
0375     { QSharedPointer copy(t); swap(copy); }
0376     template <typename Deleter>
0377     inline void reset(T *t, Deleter deleter)
0378     { QSharedPointer copy(t, deleter); swap(copy); }
0379 
0380     template <class X>
0381     QSharedPointer<X> staticCast() const &
0382     {
0383         return qSharedPointerCast<X>(*this);
0384     }
0385 
0386     template <class X>
0387     QSharedPointer<X> staticCast() &&
0388     {
0389         return qSharedPointerCast<X>(std::move(*this));
0390     }
0391 
0392     template <class X>
0393     QSharedPointer<X> dynamicCast() const &
0394     {
0395         return qSharedPointerDynamicCast<X>(*this);
0396     }
0397 
0398     template <class X>
0399     QSharedPointer<X> dynamicCast() &&
0400     {
0401         return qSharedPointerDynamicCast<X>(std::move(*this));
0402     }
0403 
0404     template <class X>
0405     QSharedPointer<X> constCast() const &
0406     {
0407         return qSharedPointerConstCast<X>(*this);
0408     }
0409 
0410     template <class X>
0411     QSharedPointer<X> constCast() &&
0412     {
0413         return qSharedPointerConstCast<X>(std::move(*this));
0414     }
0415 
0416 #ifndef QT_NO_QOBJECT
0417     template <class X>
0418     QSharedPointer<X> objectCast() const &
0419     {
0420         return qSharedPointerObjectCast<X>(*this);
0421     }
0422 
0423     template <class X>
0424     QSharedPointer<X> objectCast() &&
0425     {
0426         return qSharedPointerObjectCast<X>(std::move(*this));
0427     }
0428 #endif
0429 
0430     inline void clear() { QSharedPointer copy; swap(copy); }
0431 
0432     [[nodiscard]] QWeakPointer<T> toWeakRef() const;
0433 
0434     template <typename... Args>
0435     [[nodiscard]] static QSharedPointer create(Args && ...arguments)
0436     {
0437         typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
0438 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
0439         typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
0440 # else
0441         typename Private::DestroyerFn destroy = &Private::deleter;
0442 # endif
0443         typename Private::DestroyerFn noDestroy = &Private::noDeleter;
0444         QSharedPointer result(Qt::Uninitialized);
0445         typename std::remove_cv<T>::type *ptr;
0446         result.d = Private::create(&ptr, noDestroy);
0447 
0448         // now initialize the data
0449         new (ptr) T(std::forward<Args>(arguments)...);
0450         result.value.reset(ptr);
0451         result.d->destroyer = destroy;
0452         result.d->setQObjectShared(result.value.get(), true);
0453 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
0454         internalSafetyCheckAdd(result.d, result.value.get());
0455 # endif
0456         result.enableSharedFromThis(result.data());
0457         return result;
0458     }
0459 
0460     template <typename X>
0461     bool owner_before(const QSharedPointer<X> &other) const noexcept
0462     { return std::less<>()(d, other.d); }
0463     template <typename X>
0464     bool owner_before(const QWeakPointer<X> &other) const noexcept
0465     { return std::less<>()(d, other.d); }
0466 
0467     template <typename X>
0468     bool owner_equal(const QSharedPointer<X> &other) const noexcept
0469     { return d == other.d; }
0470     template <typename X>
0471     bool owner_equal(const QWeakPointer<X> &other) const noexcept
0472     { return d == other.d; }
0473 
0474     size_t owner_hash() const noexcept
0475     { return std::hash<Data *>()(d); }
0476 
0477 private:
0478     template <typename X>
0479     friend bool comparesEqual(const QSharedPointer &lhs, const QSharedPointer<X> &rhs) noexcept
0480     { return lhs.data() == rhs.data(); }
0481     template <typename X>
0482     friend Qt::strong_ordering
0483     compareThreeWay(const QSharedPointer &lhs, const QSharedPointer<X> &rhs) noexcept
0484     {
0485         return Qt::compareThreeWay(lhs.value, rhs.data());
0486     }
0487     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, QSharedPointer<T>, QSharedPointer<X>,
0488                                          /* non-constexpr */, noexcept(true),
0489                                          template <typename X>)
0490 
0491     template <typename X>
0492     friend bool comparesEqual(const QSharedPointer &lhs, X *rhs) noexcept
0493     { return lhs.data() == rhs; }
0494     template <typename X>
0495     friend Qt::strong_ordering compareThreeWay(const QSharedPointer &lhs, X *rhs) noexcept
0496     { return Qt::compareThreeWay(lhs.value, rhs); }
0497     Q_DECLARE_STRONGLY_ORDERED(QSharedPointer, X*, template <typename X>)
0498 
0499     friend bool comparesEqual(const QSharedPointer &lhs, std::nullptr_t) noexcept
0500     { return lhs.data() == nullptr; }
0501     friend Qt::strong_ordering
0502     compareThreeWay(const QSharedPointer &lhs, std::nullptr_t) noexcept
0503     { return Qt::compareThreeWay(lhs.value, nullptr); }
0504     Q_DECLARE_STRONGLY_ORDERED(QSharedPointer, std::nullptr_t)
0505 
0506     Q_NODISCARD_CTOR
0507     explicit QSharedPointer(Qt::Initialization) {}
0508 
0509     void deref() noexcept
0510     { deref(d); }
0511     static void deref(Data *dd) noexcept
0512     {
0513         if (!dd) return;
0514         if (!dd->strongref.deref()) {
0515             dd->destroy();
0516         }
0517         if (!dd->weakref.deref())
0518             delete dd;
0519     }
0520 
0521     template <class X>
0522     inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
0523     {
0524         ptr->initializeFromSharedPointer(constCast<typename std::remove_cv<T>::type>());
0525     }
0526 
0527     inline void enableSharedFromThis(...) {}
0528 
0529     template <typename X, typename Deleter>
0530     inline void internalConstruct(X *ptr, Deleter deleter)
0531     {
0532         typedef QtSharedPointer::ExternalRefCountWithCustomDeleter<X, Deleter> Private;
0533 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
0534         typename Private::DestroyerFn actualDeleter = &Private::safetyCheckDeleter;
0535 # else
0536         typename Private::DestroyerFn actualDeleter = &Private::deleter;
0537 # endif
0538         d = Private::create(ptr, deleter, actualDeleter);
0539 
0540 #ifdef QT_SHAREDPOINTER_TRACK_POINTERS
0541         internalSafetyCheckAdd(d, ptr);
0542 #endif
0543         enableSharedFromThis(ptr);
0544     }
0545 
0546     void internalSwap(QSharedPointer &other) noexcept
0547     {
0548         qt_ptr_swap(d, other.d);
0549         qt_ptr_swap(this->value, other.value);
0550     }
0551 
0552     template <class X> friend class QSharedPointer;
0553     template <class X> friend class QWeakPointer;
0554     template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
0555     template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::movePointer(X * ptr, QSharedPointer<Y> &&src);
0556     void ref() const noexcept { d->weakref.ref(); d->strongref.ref(); }
0557 
0558     inline void internalSet(Data *o, T *actual)
0559     {
0560         if (o) {
0561             // increase the strongref, but never up from zero
0562             // or less (-1 is used by QWeakPointer on untracked QObject)
0563             int tmp = o->strongref.loadRelaxed();
0564             while (tmp > 0) {
0565                 // try to increment from "tmp" to "tmp + 1"
0566                 if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
0567                     break;   // succeeded
0568                 tmp = o->strongref.loadRelaxed();  // failed, try again
0569             }
0570 
0571             if (tmp > 0)
0572                 o->weakref.ref();
0573             else
0574                 o = nullptr;
0575         }
0576 
0577         qt_ptr_swap(d, o);
0578         this->value.reset(actual);
0579         if (!d || d->strongref.loadRelaxed() == 0)
0580             this->value = nullptr;
0581 
0582         // dereference saved data
0583         deref(o);
0584     }
0585 
0586     Qt::totally_ordered_wrapper<Type *> value;
0587     Data *d;
0588 };
0589 
0590 template <class T>
0591 class QWeakPointer
0592 {
0593     typedef QtSharedPointer::ExternalRefCountData Data;
0594     template <typename X>
0595     using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
0596 
0597     template <typename X>
0598     using IfVirtualBase = typename std::enable_if<qxp::is_virtual_base_of_v<T, X>, bool>::type;
0599 
0600     template <typename X>
0601     using IfNotVirtualBase = typename std::enable_if<!qxp::is_virtual_base_of_v<T, X>, bool>::type;
0602 
0603 public:
0604     typedef T element_type;
0605     typedef T value_type;
0606     typedef value_type *pointer;
0607     typedef const value_type *const_pointer;
0608     typedef value_type &reference;
0609     typedef const value_type &const_reference;
0610     typedef qptrdiff difference_type;
0611 
0612     bool isNull() const noexcept { return d == nullptr || d->strongref.loadRelaxed() == 0 || value == nullptr; }
0613     explicit operator bool() const noexcept { return !isNull(); }
0614     bool operator !() const noexcept { return isNull(); }
0615 
0616     Q_NODISCARD_CTOR
0617     constexpr QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
0618     inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
0619 
0620     Q_NODISCARD_CTOR
0621     QWeakPointer(const QWeakPointer &other) noexcept : d(other.d), value(other.value)
0622     { if (d) d->weakref.ref(); }
0623     Q_NODISCARD_CTOR
0624     QWeakPointer(QWeakPointer &&other) noexcept
0625         : d(other.d), value(other.value)
0626     {
0627         other.d = nullptr;
0628         other.value = nullptr;
0629     }
0630     QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QWeakPointer)
0631 
0632     template <class X, IfCompatible<X> = true, IfNotVirtualBase<X> = true>
0633     Q_NODISCARD_CTOR
0634     QWeakPointer(QWeakPointer<X> &&other) noexcept
0635         : d(std::exchange(other.d, nullptr)),
0636           value(std::exchange(other.value, nullptr))
0637     {
0638     }
0639 
0640     template <class X, IfCompatible<X> = true, IfVirtualBase<X> = true>
0641     Q_NODISCARD_CTOR
0642     QWeakPointer(QWeakPointer<X> &&other) noexcept
0643         : d(other.d), value(other.toStrongRef().get()) // must go through QSharedPointer, see below
0644     {
0645         other.d = nullptr;
0646         other.value = nullptr;
0647     }
0648 
0649     template <class X, IfCompatible<X> = true>
0650     QWeakPointer &operator=(QWeakPointer<X> &&other) noexcept
0651     {
0652         QWeakPointer moved(std::move(other));
0653         swap(moved);
0654         return *this;
0655     }
0656 
0657     QWeakPointer &operator=(const QWeakPointer &other) noexcept
0658     {
0659         QWeakPointer copy(other);
0660         swap(copy);
0661         return *this;
0662     }
0663 
0664     void swap(QWeakPointer &other) noexcept
0665     {
0666         qt_ptr_swap(this->d, other.d);
0667         qt_ptr_swap(this->value, other.value);
0668     }
0669 
0670     Q_NODISCARD_CTOR
0671     inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
0672     { if (d) d->weakref.ref();}
0673     inline QWeakPointer &operator=(const QSharedPointer<T> &o)
0674     {
0675         internalSet(o.d, o.value.get());
0676         return *this;
0677     }
0678 
0679     template <class X, IfCompatible<X> = true>
0680     Q_NODISCARD_CTOR
0681     inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr)
0682     { *this = o; }
0683 
0684     template <class X, IfCompatible<X> = true>
0685     inline QWeakPointer &operator=(const QWeakPointer<X> &o)
0686     {
0687         // conversion between X and T could require access to the virtual table
0688         // so force the operation to go through QSharedPointer
0689         *this = o.toStrongRef();
0690         return *this;
0691     }
0692 
0693     template <class X, IfCompatible<X> = true>
0694     Q_NODISCARD_CTOR
0695     inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr)
0696     { *this = o; }
0697 
0698     template <class X, IfCompatible<X> = true>
0699     inline QWeakPointer &operator=(const QSharedPointer<X> &o)
0700     {
0701         internalSet(o.d, o.data());
0702         return *this;
0703     }
0704 
0705     inline void clear() { *this = QWeakPointer(); }
0706 
0707     [[nodiscard]] QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
0708     // std::weak_ptr compatibility:
0709     [[nodiscard]] QSharedPointer<T> lock() const { return toStrongRef(); }
0710 
0711     template <class X>
0712     bool operator==(const QWeakPointer<X> &o) const noexcept
0713     { return d == o.d && value == static_cast<const T *>(o.value); }
0714 
0715     template <class X>
0716     bool operator!=(const QWeakPointer<X> &o) const noexcept
0717     { return !(*this == o); }
0718 
0719     template <class X>
0720     bool operator==(const QSharedPointer<X> &o) const noexcept
0721     { return d == o.d; }
0722 
0723     template <class X>
0724     bool operator!=(const QSharedPointer<X> &o) const noexcept
0725     { return !(*this == o); }
0726 
0727     template <typename X>
0728     friend bool operator==(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
0729     { return p2 == p1; }
0730     template <typename X>
0731     friend bool operator!=(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
0732     { return p2 != p1; }
0733 
0734     friend bool operator==(const QWeakPointer &p, std::nullptr_t)
0735     { return p.isNull(); }
0736     friend bool operator==(std::nullptr_t, const QWeakPointer &p)
0737     { return p.isNull(); }
0738     friend bool operator!=(const QWeakPointer &p, std::nullptr_t)
0739     { return !p.isNull(); }
0740     friend bool operator!=(std::nullptr_t, const QWeakPointer &p)
0741     { return !p.isNull(); }
0742 
0743     template <typename X>
0744     bool owner_before(const QWeakPointer<X> &other) const noexcept
0745     { return std::less<>()(d, other.d); }
0746     template <typename X>
0747     bool owner_before(const QSharedPointer<X> &other) const noexcept
0748     { return std::less<>()(d, other.d); }
0749 
0750     template <typename X>
0751     bool owner_equal(const QWeakPointer<X> &other) const noexcept
0752     { return d == other.d; }
0753     template <typename X>
0754     bool owner_equal(const QSharedPointer<X> &other) const noexcept
0755     { return d == other.d; }
0756 
0757     size_t owner_hash() const noexcept
0758     { return std::hash<Data *>()(d); }
0759 
0760 private:
0761     friend struct QtPrivate::EnableInternalData;
0762     template <class X> friend class QSharedPointer;
0763     template <class X> friend class QWeakPointer;
0764     template <class X> friend class QPointer;
0765 
0766     template <class X>
0767     inline QWeakPointer &assign(X *ptr)
0768     { return *this = QWeakPointer<T>(ptr, true); }
0769 
0770 #ifndef QT_NO_QOBJECT
0771     template <class X, IfCompatible<X> = true>
0772     Q_NODISCARD_CTOR
0773     inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
0774     { }
0775 #endif
0776 
0777     inline void internalSet(Data *o, T *actual)
0778     {
0779         if (d == o) return;
0780         if (o)
0781             o->weakref.ref();
0782         if (d && !d->weakref.deref())
0783             delete d;
0784         d = o;
0785         value = actual;
0786     }
0787 
0788     // ### TODO - QTBUG-88102: remove all users of this API; no one should ever
0789     // access a weak pointer's data but the weak pointer itself
0790     inline T *internalData() const noexcept
0791     {
0792         return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : value;
0793     }
0794 
0795     Data *d;
0796     T *value;
0797 };
0798 
0799 namespace QtPrivate {
0800 struct EnableInternalData {
0801     template <typename T>
0802     static T *internalData(const QWeakPointer<T> &p) noexcept { return p.internalData(); }
0803 };
0804 // hack to delay name lookup to instantiation time by making
0805 // EnableInternalData a dependent name:
0806 template <typename T>
0807 struct EnableInternalDataWrap : EnableInternalData {};
0808 }
0809 
0810 template <class T>
0811 class QEnableSharedFromThis
0812 {
0813 protected:
0814     QEnableSharedFromThis() = default;
0815     QEnableSharedFromThis(const QEnableSharedFromThis &) {}
0816     QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; }
0817 
0818 public:
0819     inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
0820     inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
0821 
0822 private:
0823     template <class X> friend class QSharedPointer;
0824     template <class X>
0825     inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
0826     {
0827         weakPointer = ptr;
0828     }
0829 
0830     mutable QWeakPointer<T> weakPointer;
0831 };
0832 
0833 //
0834 // operator-
0835 //
0836 template <class T, class X>
0837 Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
0838 {
0839     return ptr1.data() - ptr2.data();
0840 }
0841 template <class T, class X>
0842 Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
0843 {
0844     return ptr1.data() - ptr2;
0845 }
0846 template <class T, class X>
0847 Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
0848 {
0849     return ptr1 - ptr2.data();
0850 }
0851 
0852 //
0853 // qHash
0854 //
0855 template <class T>
0856 Q_INLINE_TEMPLATE size_t qHash(const QSharedPointer<T> &ptr, size_t seed = 0)
0857 {
0858     return qHash(ptr.data(), seed);
0859 }
0860 
0861 
0862 template <class T>
0863 Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
0864 {
0865     return QWeakPointer<T>(*this);
0866 }
0867 
0868 template <class T>
0869 inline void swap(QSharedPointer<T> &p1, QSharedPointer<T> &p2) noexcept
0870 { p1.swap(p2); }
0871 
0872 template <class T>
0873 inline void swap(QWeakPointer<T> &p1, QWeakPointer<T> &p2) noexcept
0874 { p1.swap(p2); }
0875 
0876 namespace QtSharedPointer {
0877 // helper functions:
0878     template <class X, class T>
0879     Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
0880     {
0881         QSharedPointer<X> result;
0882         result.internalSet(src.d, ptr);
0883         return result;
0884     }
0885 
0886     template <class X, class T>
0887     Q_INLINE_TEMPLATE QSharedPointer<X> movePointer(X *ptr, QSharedPointer<T> &&src)
0888     {
0889         QSharedPointer<X> result;
0890         result.d = std::exchange(src.d, nullptr);
0891         result.value.reset(ptr);
0892         src.value.reset(nullptr);
0893         return result;
0894     }
0895 }
0896 
0897 // cast operators
0898 template <class X, class T>
0899 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
0900 {
0901     X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0902     return QtSharedPointer::copyAndSetPointer(ptr, src);
0903 }
0904 template <class X, class T>
0905 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(QSharedPointer<T> &&src)
0906 {
0907     X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0908     return QtSharedPointer::movePointer(ptr, std::move(src));
0909 }
0910 template <class X, class T>
0911 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
0912 {
0913     return qSharedPointerCast<X>(src.toStrongRef());
0914 }
0915 
0916 template <class X, class T>
0917 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
0918 {
0919     X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0920     if (!ptr)
0921         return QSharedPointer<X>();
0922     return QtSharedPointer::copyAndSetPointer(ptr, src);
0923 }
0924 template <class X, class T>
0925 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(QSharedPointer<T> &&src)
0926 {
0927     X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0928     if (!ptr)
0929         return QSharedPointer<X>();
0930     return QtSharedPointer::movePointer(ptr, std::move(src));
0931 }
0932 template <class X, class T>
0933 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
0934 {
0935     return qSharedPointerDynamicCast<X>(src.toStrongRef());
0936 }
0937 
0938 template <class X, class T>
0939 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
0940 {
0941     X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0942     return QtSharedPointer::copyAndSetPointer(ptr, src);
0943 }
0944 template <class X, class T>
0945 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(QSharedPointer<T> &&src)
0946 {
0947     X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0948     return QtSharedPointer::movePointer(ptr, std::move(src));
0949 }
0950 template <class X, class T>
0951 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
0952 {
0953     return qSharedPointerConstCast<X>(src.toStrongRef());
0954 }
0955 
0956 template <class X, class T>
0957 Q_INLINE_TEMPLATE
0958 QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
0959 {
0960     return qSharedPointerCast<X>(src).toWeakRef();
0961 }
0962 
0963 #ifndef QT_NO_QOBJECT
0964 template <class X, class T>
0965 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
0966 {
0967     X *ptr = qobject_cast<X *>(src.data());
0968     if (!ptr)
0969         return QSharedPointer<X>();
0970     return QtSharedPointer::copyAndSetPointer(ptr, src);
0971 }
0972 template <class X, class T>
0973 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(QSharedPointer<T> &&src)
0974 {
0975     X *ptr = qobject_cast<X *>(src.data());
0976     if (!ptr)
0977         return QSharedPointer<X>();
0978     return QtSharedPointer::movePointer(ptr, std::move(src));
0979 }
0980 template <class X, class T>
0981 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
0982 {
0983     return qSharedPointerObjectCast<X>(src.toStrongRef());
0984 }
0985 
0986 template <class X, class T>
0987 inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
0988 qobject_cast(const QSharedPointer<T> &src)
0989 {
0990     return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(src);
0991 }
0992 template <class X, class T>
0993 inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
0994 qobject_cast(QSharedPointer<T> &&src)
0995 {
0996     return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(std::move(src));
0997 }
0998 template <class X, class T>
0999 inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
1000 qobject_cast(const QWeakPointer<T> &src)
1001 {
1002     return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(src);
1003 }
1004 
1005 /// ### TODO - QTBUG-88102: make this use toStrongRef() (once support for
1006 /// storing non-managed QObjects in QWeakPointer is removed)
1007 template<typename T>
1008 QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
1009 qWeakPointerFromVariant(const QVariant &variant)
1010 {
1011     return QWeakPointer<T>(qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(QtSharedPointer::weakPointerFromVariant_internal(variant))));
1012 }
1013 template<typename T>
1014 QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
1015 qSharedPointerFromVariant(const QVariant &variant)
1016 {
1017     return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
1018 }
1019 
1020 // std::shared_ptr helpers
1021 
1022 template <typename X, class T>
1023 std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
1024 {
1025     using element_type = typename std::shared_ptr<X>::element_type;
1026     if (auto ptr = qobject_cast<element_type *>(src.get()))
1027         return std::shared_ptr<X>(src, ptr);
1028     return std::shared_ptr<X>();
1029 }
1030 
1031 template <typename X, class T>
1032 std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
1033 {
1034     using element_type = typename std::shared_ptr<X>::element_type;
1035     auto castResult = qobject_cast<element_type *>(src.get());
1036     if (castResult) {
1037         // C++2a's move aliasing constructor will leave src empty.
1038         // Before C++2a we don't really know if the compiler has support for it.
1039         // The move aliasing constructor is the resolution for LWG2996,
1040         // which does not impose a feature-testing macro. So: clear src.
1041         return std::shared_ptr<X>(std::exchange(src, nullptr), castResult);
1042     }
1043     return std::shared_ptr<X>();
1044 }
1045 
1046 template <typename X, class T>
1047 std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
1048 {
1049     return qobject_pointer_cast<X>(src);
1050 }
1051 
1052 template <typename X, class T>
1053 std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
1054 {
1055     return qobject_pointer_cast<X>(std::move(src));
1056 }
1057 
1058 #endif
1059 
1060 template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_RELOCATABLE_TYPE);
1061 template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_RELOCATABLE_TYPE);
1062 
1063 
1064 QT_END_NAMESPACE
1065 
1066 #endif