LCOV - code coverage report
Current view: top level - usr/include/x86_64-linux-gnu/qt5/QtCore - qsharedpointer_impl.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 20 0.0 %
Date: 2016-09-12 13:07:23 Functions: 0 9 0.0 %

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

Generated by: LCOV version 1.11