LCOV - code coverage report
Current view: top level - home/aheinecke/dev/main/qt5/include/QtCore - qsharedpointer_impl.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 20 0.0 %
Date: 2018-11-14 16:53:58 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /****************************************************************************
       2             : **
       3             : ** Copyright (C) 2016 The Qt Company Ltd.
       4             : ** Copyright (C) 2016 Intel Corporation.
       5             : ** Contact: https://www.qt.io/licensing/
       6             : **
       7             : ** This file is part of the QtCore module of the Qt Toolkit.
       8             : **
       9             : ** $QT_BEGIN_LICENSE:LGPL$
      10             : ** Commercial License Usage
      11             : ** Licensees holding valid commercial Qt licenses may use this file in
      12             : ** accordance with the commercial license agreement provided with the
      13             : ** Software or, alternatively, in accordance with the terms contained in
      14             : ** a written agreement between you and The Qt Company. For licensing terms
      15             : ** and conditions see https://www.qt.io/terms-conditions. For further
      16             : ** information use the contact form at https://www.qt.io/contact-us.
      17             : **
      18             : ** GNU Lesser General Public License Usage
      19             : ** Alternatively, this file may be used under the terms of the GNU Lesser
      20             : ** General Public License version 3 as published by the Free Software
      21             : ** Foundation and appearing in the file LICENSE.LGPL3 included in the
      22             : ** packaging of this file. Please review the following information to
      23             : ** ensure the GNU Lesser General Public License version 3 requirements
      24             : ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
      25             : **
      26             : ** GNU General Public License Usage
      27             : ** Alternatively, this file may be used under the terms of the GNU
      28             : ** General Public License version 2.0 or (at your option) the GNU General
      29             : ** Public license version 3 or any later version approved by the KDE Free
      30             : ** Qt Foundation. The licenses are as published by the Free Software
      31             : ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
      32             : ** included in the packaging of this file. Please review the following
      33             : ** information to ensure the GNU General Public License requirements will
      34             : ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
      35             : ** https://www.gnu.org/licenses/gpl-3.0.html.
      36             : **
      37             : ** $QT_END_LICENSE$
      38             : **
      39             : ****************************************************************************/
      40             : 
      41             : #ifndef Q_QDOC
      42             : 
      43             : #ifndef QSHAREDPOINTER_H
      44             : #error Do not include qsharedpointer_impl.h directly
      45             : #endif
      46             : 
      47             : #if 0
      48             : #pragma qt_sync_skip_header_check
      49             : #pragma qt_sync_stop_processing
      50             : #endif
      51             : 
      52             : #if 0
      53             : // These macros are duplicated here to make syncqt not complain a about
      54             : // this header, as we have a "qt_sync_stop_processing" below, which in turn
      55             : // is here because this file contains a template mess and duplicates the
      56             : // classes found in qsharedpointer.h
      57             : QT_BEGIN_NAMESPACE
      58             : QT_END_NAMESPACE
      59             : #pragma qt_sync_stop_processing
      60             : #endif
      61             : 
      62             : #include <new>
      63             : #include <QtCore/qatomic.h>
      64             : #include <QtCore/qobject.h>    // for qobject_cast
      65             : #if QT_DEPRECATED_SINCE(5, 6)
      66             : #include <QtCore/qhash.h>
      67             : #endif
      68             : #include <QtCore/qhashfunctions.h>
      69             : 
      70             : QT_BEGIN_NAMESPACE
      71             : 
      72             : 
      73             : // Macro QSHAREDPOINTER_VERIFY_AUTO_CAST
      74             : //  generates a compiler error if the following construct isn't valid:
      75             : //    T *ptr1;
      76             : //    X *ptr2 = ptr1;
      77             : //
      78             : #ifdef QT_NO_DEBUG
      79             : # define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X)          qt_noop()
      80             : #else
      81             : 
      82             : template<typename T> inline void qt_sharedpointer_cast_check(T *) { }
      83             : # define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X)          \
      84             :     qt_sharedpointer_cast_check<T>(static_cast<X *>(0))
      85             : #endif
      86             : 
      87             : //
      88             : // forward declarations
      89             : //
      90             : template <class T> class QWeakPointer;
      91             : template <class T> class QSharedPointer;
      92             : template <class T> class QEnableSharedFromThis;
      93             : 
      94             : class QVariant;
      95             : 
      96             : template <class X, class T>
      97             : QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr);
      98             : template <class X, class T>
      99             : QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
     100             : template <class X, class T>
     101             : QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
     102             : 
     103             : #ifndef QT_NO_QOBJECT
     104             : template <class X, class T>
     105             : QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
     106             : #endif
     107             : 
     108             : namespace QtSharedPointer {
     109             :     template <class T> class ExternalRefCount;
     110             : 
     111             :     template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
     112             : 
     113             :     // used in debug mode to verify the reuse of pointers
     114             :     Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *);
     115             :     Q_CORE_EXPORT void internalSafetyCheckRemove(const void *);
     116             : 
     117             :     template <class T, typename Klass, typename RetVal>
     118             :     inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
     119             :     { (t->*memberDeleter)(); }
     120             :     template <class T, typename Deleter>
     121             :     inline void executeDeleter(T *t, Deleter d)
     122             :     { d(t); }
     123             :     struct NormalDeleter {};
     124             : 
     125             :     // this uses partial template specialization
     126             :     template <class T> struct RemovePointer;
     127             :     template <class T> struct RemovePointer<T *> { typedef T Type; };
     128             :     template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
     129             :     template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
     130             : 
     131             :     // This class is the d-pointer of QSharedPointer and QWeakPointer.
     132             :     //
     133             :     // It is a reference-counted reference counter. "strongref" is the inner
     134             :     // reference counter, and it tracks the lifetime of the pointer itself.
     135             :     // "weakref" is the outer reference counter and it tracks the lifetime of
     136             :     // the ExternalRefCountData object.
     137             :     //
     138             :     // The deleter is stored in the destroyer member and is always a pointer to
     139             :     // a static function in ExternalRefCountWithCustomDeleter or in
     140             :     // ExternalRefCountWithContiguousData
     141             :     struct ExternalRefCountData
     142             :     {
     143             :         typedef void (*DestroyerFn)(ExternalRefCountData *);
     144             :         QBasicAtomicInt weakref;
     145             :         QBasicAtomicInt strongref;
     146             :         DestroyerFn destroyer;
     147             : 
     148             :         inline ExternalRefCountData(DestroyerFn d)
     149             :             : destroyer(d)
     150             :         {
     151             :             strongref.store(1);
     152             :             weakref.store(1);
     153             :         }
     154             :         inline ExternalRefCountData(Qt::Initialization) { }
     155           0 :         ~ExternalRefCountData() { Q_ASSERT(!weakref.load()); Q_ASSERT(strongref.load() <= 0); }
     156             : 
     157             :         void destroy() { destroyer(this); }
     158             : 
     159             : #ifndef QT_NO_QOBJECT
     160             :         Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
     161             :         Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
     162             :         Q_CORE_EXPORT void checkQObjectShared(const QObject *);
     163             : #endif
     164             :         inline void checkQObjectShared(...) { }
     165             :         inline void setQObjectShared(...) { }
     166             : 
     167           0 :         inline void operator delete(void *ptr) { ::operator delete(ptr); }
     168             :         inline void operator delete(void *, void *) { }
     169             :     };
     170             :     // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit)
     171             : 
     172             :     template <class T, typename Deleter>
     173             :     struct CustomDeleter
     174             :     {
     175             :         Deleter deleter;
     176             :         T *ptr;
     177             : 
     178             :         CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
     179             :         void execute() { executeDeleter(ptr, deleter); }
     180             :     };
     181             :     // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding
     182             :     // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding
     183             :     // for Deleter = function pointer:  8 (32-bit) / 16 (64-bit)
     184             :     // for Deleter = PMF: 12 (32-bit) / 24 (64-bit)  (GCC)
     185             : 
     186             :     // This specialization of CustomDeleter for a deleter of type NormalDeleter
     187             :     // is an optimization: instead of storing a pointer to a function that does
     188             :     // the deleting, we simply delete the pointer ourselves.
     189             :     template <class T>
     190             :     struct CustomDeleter<T, NormalDeleter>
     191             :     {
     192             :         T *ptr;
     193             : 
     194             :         CustomDeleter(T *p, NormalDeleter) : ptr(p) {}
     195             :         void execute() { delete ptr; }
     196             :     };
     197             :     // sizeof(CustomDeleter specialization) = sizeof(void*)
     198             : 
     199             :     // This class extends ExternalRefCountData and implements
     200             :     // the static function that deletes the object. The pointer and the
     201             :     // custom deleter are kept in the "extra" member so we can construct
     202             :     // and destruct it independently of the full structure.
     203             :     template <class T, typename Deleter>
     204             :     struct ExternalRefCountWithCustomDeleter: public ExternalRefCountData
     205             :     {
     206             :         typedef ExternalRefCountWithCustomDeleter Self;
     207             :         typedef ExternalRefCountData BaseClass;
     208             :         CustomDeleter<T, Deleter> extra;
     209             : 
     210             :         static inline void deleter(ExternalRefCountData *self)
     211             :         {
     212             :             Self *realself = static_cast<Self *>(self);
     213             :             realself->extra.execute();
     214             : 
     215             :             // delete the deleter too
     216             :             realself->extra.~CustomDeleter<T, Deleter>();
     217             :         }
     218             :         static void safetyCheckDeleter(ExternalRefCountData *self)
     219             :         {
     220             :             internalSafetyCheckRemove(self);
     221             :             deleter(self);
     222             :         }
     223             : 
     224             :         static inline Self *create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
     225             :         {
     226             :             Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
     227             : 
     228             :             // initialize the two sub-objects
     229             :             new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter);
     230             :             new (d) BaseClass(actualDeleter); // can't throw
     231             : 
     232             :             return d;
     233             :         }
     234             :     private:
     235             :         // prevent construction
     236             :         ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE;
     237             :         ~ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE;
     238             :         Q_DISABLE_COPY(ExternalRefCountWithCustomDeleter)
     239             :     };
     240             : 
     241             :     // This class extends ExternalRefCountData and adds a "T"
     242             :     // member. That way, when the create() function is called, we allocate
     243             :     // memory for both QSharedPointer's d-pointer and the actual object being
     244             :     // tracked.
     245             :     template <class T>
     246             :     struct ExternalRefCountWithContiguousData: public ExternalRefCountData
     247             :     {
     248             :         typedef ExternalRefCountData Parent;
     249             :         T data;
     250             : 
     251             :         static void deleter(ExternalRefCountData *self)
     252             :         {
     253             :             ExternalRefCountWithContiguousData *that =
     254             :                     static_cast<ExternalRefCountWithContiguousData *>(self);
     255             :             that->data.~T();
     256             :             Q_UNUSED(that); // MSVC warns if T has a trivial destructor
     257             :         }
     258             :         static void safetyCheckDeleter(ExternalRefCountData *self)
     259             :         {
     260             :             internalSafetyCheckRemove(self);
     261             :             deleter(self);
     262             :         }
     263             :         static void noDeleter(ExternalRefCountData *) { }
     264             : 
     265             :         static inline ExternalRefCountData *create(T **ptr, DestroyerFn destroy)
     266             :         {
     267             :             ExternalRefCountWithContiguousData *d =
     268             :                 static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
     269             : 
     270             :             // initialize the d-pointer sub-object
     271             :             // leave d->data uninitialized
     272             :             new (d) Parent(destroy); // can't throw
     273             : 
     274             :             *ptr = &d->data;
     275             :             return d;
     276             :         }
     277             : 
     278             :     private:
     279             :         // prevent construction
     280             :         ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
     281             :         ~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
     282             :         Q_DISABLE_COPY(ExternalRefCountWithContiguousData)
     283             :     };
     284             : 
     285             : #ifndef QT_NO_QOBJECT
     286             :     Q_CORE_EXPORT QWeakPointer<QObject> weakPointerFromVariant_internal(const QVariant &variant);
     287             :     Q_CORE_EXPORT QSharedPointer<QObject> sharedPointerFromVariant_internal(const QVariant &variant);
     288             : #endif
     289             : } // namespace QtSharedPointer
     290             : 
     291             : template <class T> class QSharedPointer
     292             : {
     293             :     typedef T *QSharedPointer:: *RestrictedBool;
     294             :     typedef QtSharedPointer::ExternalRefCountData Data;
     295             : public:
     296             :     typedef T Type;
     297             :     typedef T element_type;
     298             :     typedef T value_type;
     299             :     typedef value_type *pointer;
     300             :     typedef const value_type *const_pointer;
     301             :     typedef value_type &reference;
     302             :     typedef const value_type &const_reference;
     303             :     typedef qptrdiff difference_type;
     304             : 
     305             :     T *data() const Q_DECL_NOTHROW { return value; }
     306             :     bool isNull() const Q_DECL_NOTHROW { return !data(); }
     307             :     operator RestrictedBool() const Q_DECL_NOTHROW { return isNull() ? Q_NULLPTR : &QSharedPointer::value; }
     308             :     bool operator !() const Q_DECL_NOTHROW { return isNull(); }
     309             :     T &operator*() const { return *data(); }
     310             :     T *operator->() const Q_DECL_NOTHROW { return data(); }
     311             : 
     312             :     Q_DECL_CONSTEXPR QSharedPointer() Q_DECL_NOTHROW : value(nullptr), d(nullptr) { }
     313             :     ~QSharedPointer() { deref(); }
     314             : 
     315             :     Q_DECL_CONSTEXPR QSharedPointer(std::nullptr_t) Q_DECL_NOTHROW : value(nullptr), d(nullptr) { }
     316             : 
     317             :     template <class X>
     318             :     inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
     319             :     { internalConstruct(ptr, QtSharedPointer::NormalDeleter()); }
     320             : 
     321             :     template <class X, typename Deleter>
     322             :     inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws
     323             :     { internalConstruct(ptr, deleter); }
     324             : 
     325             :     template <typename Deleter>
     326             :     QSharedPointer(std::nullptr_t, Deleter) : value(nullptr), d(nullptr) { }
     327             : 
     328             :     QSharedPointer(const QSharedPointer &other) Q_DECL_NOTHROW : value(other.value), d(other.d)
     329             :     { if (d) ref(); }
     330             :     QSharedPointer &operator=(const QSharedPointer &other) Q_DECL_NOTHROW
     331             :     {
     332             :         QSharedPointer copy(other);
     333             :         swap(copy);
     334             :         return *this;
     335             :     }
     336             : #ifdef Q_COMPILER_RVALUE_REFS
     337             :     QSharedPointer(QSharedPointer &&other) Q_DECL_NOTHROW
     338             :         : value(other.value), d(other.d)
     339             :     {
     340             :         other.d = Q_NULLPTR;
     341             :         other.value = Q_NULLPTR;
     342             :     }
     343             :     QSharedPointer &operator=(QSharedPointer &&other) Q_DECL_NOTHROW
     344             :     {
     345             :         QSharedPointer moved(std::move(other));
     346             :         swap(moved);
     347             :         return *this;
     348             :     }
     349             : 
     350             :     template <class X>
     351             :     QSharedPointer(QSharedPointer<X> &&other) Q_DECL_NOTHROW
     352             :         : value(other.value), d(other.d)
     353             :     {
     354             :         other.d = Q_NULLPTR;
     355             :         other.value = Q_NULLPTR;
     356             :     }
     357             : 
     358             :     template <class X>
     359             :     QSharedPointer &operator=(QSharedPointer<X> &&other) Q_DECL_NOTHROW
     360             :     {
     361             :         QSharedPointer moved(std::move(other));
     362             :         swap(moved);
     363             :         return *this;
     364             :     }
     365             : 
     366             : #endif
     367             : 
     368             :     template <class X>
     369             :     QSharedPointer(const QSharedPointer<X> &other) Q_DECL_NOTHROW : value(other.value), d(other.d)
     370             :     { if (d) ref(); }
     371             : 
     372             :     template <class X>
     373             :     inline QSharedPointer &operator=(const QSharedPointer<X> &other)
     374             :     {
     375             :         QSharedPointer copy(other);
     376             :         swap(copy);
     377             :         return *this;
     378             :     }
     379             : 
     380             :     template <class X>
     381             :     inline QSharedPointer(const QWeakPointer<X> &other) : value(Q_NULLPTR), d(Q_NULLPTR)
     382             :     { *this = other; }
     383             : 
     384             :     template <class X>
     385             :     inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
     386             :     { internalSet(other.d, other.value); return *this; }
     387             : 
     388             :     inline void swap(QSharedPointer &other)
     389             :     { this->internalSwap(other); }
     390             : 
     391             :     inline void reset() { clear(); }
     392             :     inline void reset(T *t)
     393             :     { QSharedPointer copy(t); swap(copy); }
     394             :     template <typename Deleter>
     395             :     inline void reset(T *t, Deleter deleter)
     396             :     { QSharedPointer copy(t, deleter); swap(copy); }
     397             : 
     398             :     template <class X>
     399             :     QSharedPointer<X> staticCast() const
     400             :     {
     401             :         return qSharedPointerCast<X, T>(*this);
     402             :     }
     403             : 
     404             :     template <class X>
     405             :     QSharedPointer<X> dynamicCast() const
     406             :     {
     407             :         return qSharedPointerDynamicCast<X, T>(*this);
     408             :     }
     409             : 
     410             :     template <class X>
     411             :     QSharedPointer<X> constCast() const
     412             :     {
     413             :         return qSharedPointerConstCast<X, T>(*this);
     414             :     }
     415             : 
     416             : #ifndef QT_NO_QOBJECT
     417             :     template <class X>
     418             :     QSharedPointer<X> objectCast() const
     419             :     {
     420             :         return qSharedPointerObjectCast<X, T>(*this);
     421             :     }
     422             : #endif
     423             : 
     424             :     inline void clear() { QSharedPointer copy; swap(copy); }
     425             : 
     426             :     QWeakPointer<T> toWeakRef() const;
     427             : 
     428             :     template <typename... Args>
     429             :     static QSharedPointer create(Args && ...arguments)
     430             :     {
     431             :         typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
     432             : # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
     433             :         typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
     434             : # else
     435             :         typename Private::DestroyerFn destroy = &Private::deleter;
     436             : # endif
     437             :         typename Private::DestroyerFn noDestroy = &Private::noDeleter;
     438             :         QSharedPointer result(Qt::Uninitialized);
     439             :         result.d = Private::create(&result.value, noDestroy);
     440             : 
     441             :         // now initialize the data
     442             :         new (result.data()) T(std::forward<Args>(arguments)...);
     443             :         result.d->destroyer = destroy;
     444             :         result.d->setQObjectShared(result.value, true);
     445             : # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
     446             :         internalSafetyCheckAdd(result.d, result.value);
     447             : # endif
     448             :         result.enableSharedFromThis(result.data());
     449             :         return result;
     450             :     }
     451             : 
     452             : private:
     453             :     explicit QSharedPointer(Qt::Initialization) {}
     454             : 
     455             :     void deref() Q_DECL_NOTHROW
     456             :     { deref(d); }
     457             :     static void deref(Data *dd) Q_DECL_NOTHROW
     458             :     {
     459             :         if (!dd) return;
     460             :         if (!dd->strongref.deref()) {
     461             :             dd->destroy();
     462             :         }
     463             :         if (!dd->weakref.deref())
     464             :             delete dd;
     465             :     }
     466             : 
     467             :     template <class X>
     468             :     inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
     469             :     {
     470             :         ptr->initializeFromSharedPointer(constCast<typename std::remove_cv<T>::type>());
     471             :     }
     472             : 
     473             :     inline void enableSharedFromThis(...) {}
     474             : 
     475             :     template <typename X, typename Deleter>
     476             :     inline void internalConstruct(X *ptr, Deleter deleter)
     477             :     {
     478             :         if (!ptr) {
     479             :             d = Q_NULLPTR;
     480             :             return;
     481             :         }
     482             : 
     483             :         typedef QtSharedPointer::ExternalRefCountWithCustomDeleter<X, Deleter> Private;
     484             : # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
     485             :         typename Private::DestroyerFn actualDeleter = &Private::safetyCheckDeleter;
     486             : # else
     487             :         typename Private::DestroyerFn actualDeleter = &Private::deleter;
     488             : # endif
     489             :         d = Private::create(ptr, deleter, actualDeleter);
     490             : 
     491             : #ifdef QT_SHAREDPOINTER_TRACK_POINTERS
     492             :         internalSafetyCheckAdd(d, ptr);
     493             : #endif
     494             :         d->setQObjectShared(ptr, true);
     495             :         enableSharedFromThis(ptr);
     496             :     }
     497             : 
     498             :     void internalSwap(QSharedPointer &other) Q_DECL_NOTHROW
     499             :     {
     500             :         qSwap(d, other.d);
     501             :         qSwap(this->value, other.value);
     502             :     }
     503             : 
     504             : #if defined(Q_NO_TEMPLATE_FRIENDS)
     505             : public:
     506             : #else
     507             :     template <class X> friend class QSharedPointer;
     508             :     template <class X> friend class QWeakPointer;
     509             :     template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
     510             : #endif
     511             :     void ref() const Q_DECL_NOTHROW { d->weakref.ref(); d->strongref.ref(); }
     512             : 
     513             :     inline void internalSet(Data *o, T *actual)
     514             :     {
     515             :         if (o) {
     516             :             // increase the strongref, but never up from zero
     517             :             // or less (-1 is used by QWeakPointer on untracked QObject)
     518             :             int tmp = o->strongref.load();
     519             :             while (tmp > 0) {
     520             :                 // try to increment from "tmp" to "tmp + 1"
     521             :                 if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
     522             :                     break;   // succeeded
     523             :                 tmp = o->strongref.load();  // failed, try again
     524             :             }
     525             : 
     526             :             if (tmp > 0) {
     527             :                 o->weakref.ref();
     528             :             } else {
     529             :                 o->checkQObjectShared(actual);
     530             :                 o = Q_NULLPTR;
     531             :             }
     532             :         }
     533             : 
     534             :         qSwap(d, o);
     535             :         qSwap(this->value, actual);
     536             :         if (!d || d->strongref.load() == 0)
     537             :             this->value = Q_NULLPTR;
     538             : 
     539             :         // dereference saved data
     540             :         deref(o);
     541             :     }
     542             : 
     543             :     Type *value;
     544             :     Data *d;
     545             : };
     546             : 
     547             : template <class T>
     548             : class QWeakPointer
     549             : {
     550             :     typedef T *QWeakPointer:: *RestrictedBool;
     551             :     typedef QtSharedPointer::ExternalRefCountData Data;
     552             : 
     553             : public:
     554             :     typedef T element_type;
     555             :     typedef T value_type;
     556             :     typedef value_type *pointer;
     557             :     typedef const value_type *const_pointer;
     558             :     typedef value_type &reference;
     559             :     typedef const value_type &const_reference;
     560             :     typedef qptrdiff difference_type;
     561             : 
     562             :     bool isNull() const Q_DECL_NOTHROW { return d == Q_NULLPTR || d->strongref.load() == 0 || value == Q_NULLPTR; }
     563             :     operator RestrictedBool() const Q_DECL_NOTHROW { return isNull() ? Q_NULLPTR : &QWeakPointer::value; }
     564             :     bool operator !() const Q_DECL_NOTHROW { return isNull(); }
     565           0 :     T *data() const Q_DECL_NOTHROW { return d == Q_NULLPTR || d->strongref.load() == 0 ? Q_NULLPTR : value; }
     566             : 
     567           0 :     inline QWeakPointer() Q_DECL_NOTHROW : d(Q_NULLPTR), value(Q_NULLPTR) { }
     568           0 :     inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
     569             : 
     570             : #ifndef QT_NO_QOBJECT
     571             :     // special constructor that is enabled only if X derives from QObject
     572             : #if QT_DEPRECATED_SINCE(5, 0)
     573             :     template <class X>
     574             :     QT_DEPRECATED inline QWeakPointer(X *ptr) : d(ptr ? Data::getAndRef(ptr) : Q_NULLPTR), value(ptr)
     575             :     { }
     576             : #endif
     577             : #endif
     578             : 
     579             : #if QT_DEPRECATED_SINCE(5, 0)
     580             :     template <class X>
     581             :     QT_DEPRECATED inline QWeakPointer &operator=(X *ptr)
     582             :     { return *this = QWeakPointer(ptr); }
     583             : #endif
     584             : 
     585             :     QWeakPointer(const QWeakPointer &other) Q_DECL_NOTHROW : d(other.d), value(other.value)
     586             :     { if (d) d->weakref.ref(); }
     587             : #ifdef Q_COMPILER_RVALUE_REFS
     588           0 :     QWeakPointer(QWeakPointer &&other) Q_DECL_NOTHROW
     589           0 :         : d(other.d), value(other.value)
     590             :     {
     591           0 :         other.d = Q_NULLPTR;
     592           0 :         other.value = Q_NULLPTR;
     593           0 :     }
     594           0 :     QWeakPointer &operator=(QWeakPointer &&other) Q_DECL_NOTHROW
     595           0 :     { QWeakPointer moved(std::move(other)); swap(moved); return *this; }
     596             : #endif
     597             :     QWeakPointer &operator=(const QWeakPointer &other) Q_DECL_NOTHROW
     598             :     {
     599             :         QWeakPointer copy(other);
     600             :         swap(copy);
     601             :         return *this;
     602             :     }
     603             : 
     604           0 :     void swap(QWeakPointer &other) Q_DECL_NOTHROW
     605             :     {
     606           0 :         qSwap(this->d, other.d);
     607           0 :         qSwap(this->value, other.value);
     608           0 :     }
     609             : 
     610             :     inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
     611             :     { if (d) d->weakref.ref();}
     612             :     inline QWeakPointer &operator=(const QSharedPointer<T> &o)
     613             :     {
     614             :         internalSet(o.d, o.value);
     615             :         return *this;
     616             :     }
     617             : 
     618             :     template <class X>
     619             :     inline QWeakPointer(const QWeakPointer<X> &o) : d(Q_NULLPTR), value(Q_NULLPTR)
     620             :     { *this = o; }
     621             : 
     622             :     template <class X>
     623             :     inline QWeakPointer &operator=(const QWeakPointer<X> &o)
     624             :     {
     625             :         // conversion between X and T could require access to the virtual table
     626             :         // so force the operation to go through QSharedPointer
     627             :         *this = o.toStrongRef();
     628             :         return *this;
     629             :     }
     630             : 
     631             :     template <class X>
     632             :     bool operator==(const QWeakPointer<X> &o) const Q_DECL_NOTHROW
     633             :     { return d == o.d && value == static_cast<const T *>(o.value); }
     634             : 
     635             :     template <class X>
     636             :     bool operator!=(const QWeakPointer<X> &o) const Q_DECL_NOTHROW
     637             :     { return !(*this == o); }
     638             : 
     639             :     template <class X>
     640             :     inline QWeakPointer(const QSharedPointer<X> &o) : d(Q_NULLPTR), value(Q_NULLPTR)
     641             :     { *this = o; }
     642             : 
     643             :     template <class X>
     644             :     inline QWeakPointer &operator=(const QSharedPointer<X> &o)
     645             :     {
     646             :         QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
     647             :         internalSet(o.d, o.data());
     648             :         return *this;
     649             :     }
     650             : 
     651             :     template <class X>
     652             :     bool operator==(const QSharedPointer<X> &o) const Q_DECL_NOTHROW
     653             :     { return d == o.d; }
     654             : 
     655             :     template <class X>
     656             :     bool operator!=(const QSharedPointer<X> &o) const Q_DECL_NOTHROW
     657             :     { return !(*this == o); }
     658             : 
     659             :     inline void clear() { *this = QWeakPointer(); }
     660             : 
     661             :     inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
     662             :     // std::weak_ptr compatibility:
     663             :     inline QSharedPointer<T> lock() const { return toStrongRef(); }
     664             : 
     665             : #if defined(QWEAKPOINTER_ENABLE_ARROW)
     666             :     inline T *operator->() const { return data(); }
     667             : #endif
     668             : 
     669             : private:
     670             : 
     671             : #if defined(Q_NO_TEMPLATE_FRIENDS)
     672             : public:
     673             : #else
     674             :     template <class X> friend class QSharedPointer;
     675             :     template <class X> friend class QPointer;
     676             : #endif
     677             : 
     678             :     template <class X>
     679           0 :     inline QWeakPointer &assign(X *ptr)
     680           0 :     { return *this = QWeakPointer<X>(ptr, true); }
     681             : 
     682             : #ifndef QT_NO_QOBJECT
     683             :     template <class X>
     684           0 :     inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : Q_NULLPTR), value(ptr)
     685           0 :     { }
     686             : #endif
     687             : 
     688             :     inline void internalSet(Data *o, T *actual)
     689             :     {
     690             :         if (d == o) return;
     691             :         if (o)
     692             :             o->weakref.ref();
     693             :         if (d && !d->weakref.deref())
     694             :             delete d;
     695             :         d = o;
     696             :         value = actual;
     697             :     }
     698             : 
     699             :     Data *d;
     700             :     T *value;
     701             : };
     702             : 
     703             : template <class T>
     704             : class QEnableSharedFromThis
     705             : {
     706             : protected:
     707             : #ifdef Q_COMPILER_DEFAULT_MEMBERS
     708             :     QEnableSharedFromThis() = default;
     709             : #else
     710             :     Q_DECL_CONSTEXPR QEnableSharedFromThis() {}
     711             : #endif
     712             :     QEnableSharedFromThis(const QEnableSharedFromThis &) {}
     713             :     QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; }
     714             : 
     715             : public:
     716             :     inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
     717             :     inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
     718             : 
     719             : #ifndef Q_NO_TEMPLATE_FRIENDS
     720             : private:
     721             :     template <class X> friend class QSharedPointer;
     722             : #else
     723             : public:
     724             : #endif
     725             :     template <class X>
     726             :     inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
     727             :     {
     728             :         weakPointer = ptr;
     729             :     }
     730             : 
     731             :     mutable QWeakPointer<T> weakPointer;
     732             : };
     733             : 
     734             : //
     735             : // operator== and operator!=
     736             : //
     737             : template <class T, class X>
     738             : bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
     739             : {
     740             :     return ptr1.data() == ptr2.data();
     741             : }
     742             : template <class T, class X>
     743             : bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
     744             : {
     745             :     return ptr1.data() != ptr2.data();
     746             : }
     747             : 
     748             : template <class T, class X>
     749             : bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) Q_DECL_NOTHROW
     750             : {
     751             :     return ptr1.data() == ptr2;
     752             : }
     753             : template <class T, class X>
     754             : bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
     755             : {
     756             :     return ptr1 == ptr2.data();
     757             : }
     758             : template <class T, class X>
     759             : bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) Q_DECL_NOTHROW
     760             : {
     761             :     return !(ptr1 == ptr2);
     762             : }
     763             : template <class T, class X>
     764             : bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
     765             : {
     766             :     return !(ptr2 == ptr1);
     767             : }
     768             : 
     769             : template <class T, class X>
     770             : bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) Q_DECL_NOTHROW
     771             : {
     772             :     return ptr2 == ptr1;
     773             : }
     774             : template <class T, class X>
     775             : bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) Q_DECL_NOTHROW
     776             : {
     777             :     return ptr2 != ptr1;
     778             : }
     779             : 
     780             : template<class T>
     781             : inline bool operator==(const QSharedPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
     782             : {
     783             :     return lhs.isNull();
     784             : }
     785             : 
     786             : template<class T>
     787             : inline bool operator!=(const QSharedPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
     788             : {
     789             :     return !lhs.isNull();
     790             : }
     791             : 
     792             : template<class T>
     793             : inline bool operator==(std::nullptr_t, const QSharedPointer<T> &rhs) Q_DECL_NOTHROW
     794             : {
     795             :     return rhs.isNull();
     796             : }
     797             : 
     798             : template<class T>
     799             : inline bool operator!=(std::nullptr_t, const QSharedPointer<T> &rhs) Q_DECL_NOTHROW
     800             : {
     801             :     return !rhs.isNull();
     802             : }
     803             : 
     804             : template<class T>
     805             : inline bool operator==(const QWeakPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
     806             : {
     807             :     return lhs.isNull();
     808             : }
     809             : 
     810             : template<class T>
     811             : inline bool operator!=(const QWeakPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
     812             : {
     813             :     return !lhs.isNull();
     814             : }
     815             : 
     816             : template<class T>
     817             : inline bool operator==(std::nullptr_t, const QWeakPointer<T> &rhs) Q_DECL_NOTHROW
     818             : {
     819             :     return rhs.isNull();
     820             : }
     821             : 
     822             : template<class T>
     823             : inline bool operator!=(std::nullptr_t, const QWeakPointer<T> &rhs) Q_DECL_NOTHROW
     824             : {
     825             :     return !rhs.isNull();
     826             : }
     827             : 
     828             : //
     829             : // operator-
     830             : //
     831             : template <class T, class X>
     832             : Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
     833             : {
     834             :     return ptr1.data() - ptr2.data();
     835             : }
     836             : template <class T, class X>
     837             : Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
     838             : {
     839             :     return ptr1.data() - ptr2;
     840             : }
     841             : template <class T, class X>
     842             : Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
     843             : {
     844             :     return ptr1 - ptr2.data();
     845             : }
     846             : 
     847             : //
     848             : // operator<
     849             : //
     850             : template <class T, class X>
     851             : Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
     852             : {
     853             :     using CT = typename std::common_type<T *, X *>::type;
     854             :     return std::less<CT>()(ptr1.data(), ptr2.data());
     855             : }
     856             : template <class T, class X>
     857             : Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
     858             : {
     859             :     using CT = typename std::common_type<T *, X *>::type;
     860             :     return std::less<CT>()(ptr1.data(), ptr2);
     861             : }
     862             : template <class T, class X>
     863             : Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
     864             : {
     865             :     using CT = typename std::common_type<T *, X *>::type;
     866             :     return std::less<CT>()(ptr1, ptr2.data());
     867             : }
     868             : 
     869             : //
     870             : // qHash
     871             : //
     872             : template <class T>
     873             : Q_INLINE_TEMPLATE uint qHash(const QSharedPointer<T> &ptr, uint seed = 0)
     874             : {
     875             :     return QT_PREPEND_NAMESPACE(qHash)(ptr.data(), seed);
     876             : }
     877             : 
     878             : 
     879             : template <class T>
     880             : Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
     881             : {
     882             :     return QWeakPointer<T>(*this);
     883             : }
     884             : 
     885             : template <class T>
     886             : inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2)
     887             : {
     888             :     p1.swap(p2);
     889             : }
     890             : 
     891             : QT_END_NAMESPACE
     892             : namespace std {
     893             :     template <class T>
     894             :     inline void swap(QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p2)
     895             :     { p1.swap(p2); }
     896             : }
     897             : QT_BEGIN_NAMESPACE
     898             : 
     899             : namespace QtSharedPointer {
     900             : // helper functions:
     901             :     template <class X, class T>
     902             :     Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
     903             :     {
     904             :         QSharedPointer<X> result;
     905             :         result.internalSet(src.d, ptr);
     906             :         return result;
     907             :     }
     908             : }
     909             : 
     910             : // cast operators
     911             : template <class X, class T>
     912             : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
     913             : {
     914             :     X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
     915             :     return QtSharedPointer::copyAndSetPointer(ptr, src);
     916             : }
     917             : template <class X, class T>
     918             : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
     919             : {
     920             :     return qSharedPointerCast<X, T>(src.toStrongRef());
     921             : }
     922             : 
     923             : template <class X, class T>
     924             : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
     925             : {
     926             :     X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
     927             :     if (!ptr)
     928             :         return QSharedPointer<X>();
     929             :     return QtSharedPointer::copyAndSetPointer(ptr, src);
     930             : }
     931             : template <class X, class T>
     932             : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
     933             : {
     934             :     return qSharedPointerDynamicCast<X, T>(src.toStrongRef());
     935             : }
     936             : 
     937             : template <class X, class T>
     938             : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
     939             : {
     940             :     X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
     941             :     return QtSharedPointer::copyAndSetPointer(ptr, src);
     942             : }
     943             : template <class X, class T>
     944             : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
     945             : {
     946             :     return qSharedPointerConstCast<X, T>(src.toStrongRef());
     947             : }
     948             : 
     949             : template <class X, class T>
     950             : Q_INLINE_TEMPLATE
     951             : QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
     952             : {
     953             :     return qSharedPointerCast<X, T>(src).toWeakRef();
     954             : }
     955             : 
     956             : #ifndef QT_NO_QOBJECT
     957             : template <class X, class T>
     958             : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
     959             : {
     960             :     X *ptr = qobject_cast<X *>(src.data());
     961             :     return QtSharedPointer::copyAndSetPointer(ptr, src);
     962             : }
     963             : template <class X, class T>
     964             : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
     965             : {
     966             :     return qSharedPointerObjectCast<X>(src.toStrongRef());
     967             : }
     968             : 
     969             : template <class X, class T>
     970             : inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
     971             : qobject_cast(const QSharedPointer<T> &src)
     972             : {
     973             :     return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
     974             : }
     975             : template <class X, class T>
     976             : inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
     977             : qobject_cast(const QWeakPointer<T> &src)
     978             : {
     979             :     return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
     980             : }
     981             : 
     982             : template<typename T>
     983             : QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
     984             : qWeakPointerFromVariant(const QVariant &variant)
     985             : {
     986             :     return QWeakPointer<T>(qobject_cast<T*>(QtSharedPointer::weakPointerFromVariant_internal(variant).data()));
     987             : }
     988             : template<typename T>
     989             : QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
     990             : qSharedPointerFromVariant(const QVariant &variant)
     991             : {
     992             :     return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
     993             : }
     994             : 
     995             : #endif
     996             : 
     997             : template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE);
     998             : template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_MOVABLE_TYPE);
     999             : 
    1000             : 
    1001             : QT_END_NAMESPACE
    1002             : 
    1003             : #endif

Generated by: LCOV version 1.13