qsharedpointer_impl.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
00006 **
00007 ** This file is part of the QtCore module of the Qt Toolkit.
00008 **
00009 ** $QT_BEGIN_LICENSE:LGPL$
00010 ** Commercial Usage
00011 ** Licensees holding valid Qt Commercial licenses may use this file in
00012 ** accordance with the Qt Commercial License Agreement provided with the
00013 ** Software or, alternatively, in accordance with the terms contained in
00014 ** a written agreement between you and Nokia.
00015 **
00016 ** GNU Lesser General Public License Usage
00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
00018 ** General Public License version 2.1 as published by the Free Software
00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
00020 ** packaging of this file.  Please review the following information to
00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00023 **
00024 ** In addition, as a special exception, Nokia gives you certain additional
00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
00027 **
00028 ** GNU General Public License Usage
00029 ** Alternatively, this file may be used under the terms of the GNU
00030 ** General Public License version 3.0 as published by the Free Software
00031 ** Foundation and appearing in the file LICENSE.GPL included in the
00032 ** packaging of this file.  Please review the following information to
00033 ** ensure the GNU General Public License version 3.0 requirements will be
00034 ** met: http://www.gnu.org/copyleft/gpl.html.
00035 **
00036 ** If you have questions regarding the use of this file, please contact
00037 ** Nokia at qt-info@nokia.com.
00038 ** $QT_END_LICENSE$
00039 **
00040 ****************************************************************************/
00041 
00042 #ifndef Q_QDOC
00043 
00044 #ifndef QSHAREDPOINTER_H
00045 #error Do not include qsharedpointer_impl.h directly
00046 #endif
00047 #if 0
00048 #pragma qt_sync_stop_processing
00049 #endif
00050 
00051 #include <new>
00052 #include <QtCore/qatomic.h>
00053 #include <QtCore/qobject.h>    // for qobject_cast
00054 
00055 QT_BEGIN_HEADER
00056 
00057 QT_BEGIN_NAMESPACE
00058 
00059 QT_MODULE(Core)
00060 
00061 // Macro QSHAREDPOINTER_VERIFY_AUTO_CAST
00062 //  generates a compiler error if the following construct isn't valid:
00063 //    T *ptr1;
00064 //    X *ptr2 = ptr1;
00065 //
00066 #ifdef QT_NO_DEBUG
00067 # define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X)          qt_noop()
00068 #else
00069 
00070 template<typename T> inline void qt_sharedpointer_cast_check(T *) { }
00071 # define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X)          \
00072     qt_sharedpointer_cast_check<T>(static_cast<X *>(0))
00073 #endif
00074 
00075 //
00076 // forward declarations
00077 //
00078 template <class T> class QWeakPointer;
00079 template <class T> class QSharedPointer;
00080 
00081 template <class X, class T>
00082 QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr);
00083 template <class X, class T>
00084 QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
00085 template <class X, class T>
00086 QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
00087 
00088 #ifndef QT_NO_QOBJECT
00089 template <class X, class T>
00090 QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
00091 #endif
00092 
00093 namespace QtSharedPointer {
00094     template <class T> class InternalRefCount;
00095     template <class T> class ExternalRefCount;
00096 
00097     template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
00098 
00099     // used in debug mode to verify the reuse of pointers
00100     Q_CORE_EXPORT void internalSafetyCheckAdd2(const void *, const volatile void *);
00101     Q_CORE_EXPORT void internalSafetyCheckRemove2(const void *);
00102 
00103     template <class T, typename Klass, typename RetVal>
00104     inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
00105     { (t->*memberDeleter)(); }
00106     template <class T, typename Deleter>
00107     inline void executeDeleter(T *t, Deleter d)
00108     { d(t); }
00109     template <class T> inline void normalDeleter(T *t) { delete t; }
00110 
00111     // this uses partial template specialization
00112     // the only compilers that didn't support this were MSVC 6.0 and 2002
00113     template <class T> struct RemovePointer;
00114     template <class T> struct RemovePointer<T *> { typedef T Type; };
00115     template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
00116     template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
00117 
00118     // This class provides the basic functionality of a pointer wrapper.
00119     // Its existence is mostly legacy, since originally QSharedPointer
00120     // could also be used for internally-refcounted objects.
00121     template <class T>
00122     class Basic
00123     {
00124 #ifndef Q_CC_NOKIAX86
00125         typedef T *Basic:: *RestrictedBool;
00126 #endif
00127     public:
00128         typedef T Type;
00129         typedef T element_type;
00130         typedef T value_type;
00131         typedef value_type *pointer;
00132         typedef const value_type *const_pointer;
00133         typedef value_type &reference;
00134         typedef const value_type &const_reference;
00135         typedef qptrdiff difference_type;
00136 
00137         inline T *data() const { return value; }
00138         inline bool isNull() const { return !data(); }
00139 #ifndef Q_CC_NOKIAX86
00140         inline operator RestrictedBool() const { return isNull() ? 0 : &Basic::value; }
00141 #else
00142         inline operator bool() const { return isNull() ? 0 : &Basic::value; }
00143 #endif
00144         inline bool operator !() const { return isNull(); }
00145         inline T &operator*() const { return *data(); }
00146         inline T *operator->() const { return data(); }
00147 
00148     protected:
00149         inline Basic(T *ptr = 0) : value(ptr) { }
00150         inline Basic(Qt::Initialization) { }
00151         // ~Basic();
00152 
00153         inline void internalConstruct(T *ptr)
00154         {
00155             value = ptr;
00156         }
00157 
00158 #if defined(Q_NO_TEMPLATE_FRIENDS)
00159     public:
00160 #else
00161         template <class X> friend class QT_PREPEND_NAMESPACE(QWeakPointer);
00162 #endif
00163 
00164         Type *value;
00165     };
00166 
00167     // This class is the d-pointer of QSharedPointer and QWeakPointer.
00168     //
00169     // It is a reference-counted reference counter. "strongref" is the inner
00170     // reference counter, and it tracks the lifetime of the pointer itself.
00171     // "weakref" is the outer reference counter and it tracks the lifetime of
00172     // the ExternalRefCountData object.
00173     struct ExternalRefCountData
00174     {
00175         QBasicAtomicInt weakref;
00176         QBasicAtomicInt strongref;
00177 
00178         inline ExternalRefCountData()
00179         {
00180             strongref = 1;
00181             weakref = 1;
00182         }
00183         inline ExternalRefCountData(Qt::Initialization) { }
00184         virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(strongref <= 0); }
00185 
00186         // overridden by derived classes
00187         // returns false to indicate caller should delete the pointer
00188         // returns true in case it has already done so
00189         virtual inline bool destroy() { return false; }
00190 
00191 #ifndef QT_NO_QOBJECT
00192         Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
00193         Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
00194 #endif
00195         inline void setQObjectShared(...) { }
00196     };
00197     // sizeof(ExternalRefCount) = 12 (32-bit) / 16 (64-bit)
00198 
00199     // This class extends ExternalRefCountData with a pointer
00200     // to a function, which is called by the destroy() function.
00201     struct ExternalRefCountWithDestroyFn: public ExternalRefCountData
00202     {
00203         typedef void (*DestroyerFn)(ExternalRefCountData *);
00204         DestroyerFn destroyer;
00205 
00206         inline ExternalRefCountWithDestroyFn(DestroyerFn d)
00207             : destroyer(d)
00208         { }
00209 
00210         inline bool destroy() { destroyer(this); return true; }
00211         inline void operator delete(void *ptr) { ::operator delete(ptr); }
00212         inline void operator delete(void *, void *) { }
00213     };
00214     // sizeof(ExternalRefCountWithDestroyFn) = 16 (32-bit) / 24 (64-bit)
00215 
00216     // This class extends ExternalRefCountWithDestroyFn and implements
00217     // the static function that deletes the object. The pointer and the
00218     // custom deleter are kept in the "extra" member.
00219     template <class T, typename Deleter>
00220     struct ExternalRefCountWithCustomDeleter: public ExternalRefCountWithDestroyFn
00221     {
00222         typedef ExternalRefCountWithCustomDeleter Self;
00223         typedef ExternalRefCountWithDestroyFn BaseClass;
00224 
00225         struct CustomDeleter
00226         {
00227             Deleter deleter;
00228             T *ptr;
00229 
00230             inline CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
00231         };
00232         CustomDeleter extra;
00233         // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*)
00234         // for Deleter = function pointer:  8 (32-bit) / 16 (64-bit)
00235         // for Deleter = PMF: 12 (32-bit) / 24 (64-bit)  (GCC)
00236 
00237         static inline void deleter(ExternalRefCountData *self)
00238         {
00239             Self *realself = static_cast<Self *>(self);
00240             executeDeleter(realself->extra.ptr, realself->extra.deleter);
00241 
00242             // delete the deleter too
00243             realself->extra.~CustomDeleter();
00244         }
00245         static void safetyCheckDeleter(ExternalRefCountData *self)
00246         {
00247             internalSafetyCheckRemove2(self);
00248             deleter(self);
00249         }
00250 
00251         static inline Self *create(T *ptr, Deleter userDeleter)
00252         {
00253 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
00254             DestroyerFn destroy = &safetyCheckDeleter;
00255 # else
00256             DestroyerFn destroy = &deleter;
00257 # endif
00258             Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
00259 
00260             // initialize the two sub-objects
00261             new (&d->extra) CustomDeleter(ptr, userDeleter);
00262             new (d) BaseClass(destroy); // can't throw
00263 
00264             return d;
00265         }
00266     private:
00267         // prevent construction and the emission of virtual symbols
00268         ExternalRefCountWithCustomDeleter();
00269         ~ExternalRefCountWithCustomDeleter();
00270     };
00271 
00272     // This class extends ExternalRefCountWithDestroyFn and adds a "T"
00273     // member. That way, when the create() function is called, we allocate
00274     // memory for both QSharedPointer's d-pointer and the actual object being
00275     // tracked.
00276     template <class T>
00277     struct ExternalRefCountWithContiguousData: public ExternalRefCountWithDestroyFn
00278     {
00279         typedef ExternalRefCountWithDestroyFn Parent;
00280         T data;
00281 
00282         static void deleter(ExternalRefCountData *self)
00283         {
00284             ExternalRefCountWithContiguousData *that =
00285                     static_cast<ExternalRefCountWithContiguousData *>(self);
00286             that->data.~T();
00287         }
00288         static void safetyCheckDeleter(ExternalRefCountData *self)
00289         {
00290             internalSafetyCheckRemove2(self);
00291             deleter(self);
00292         }
00293 
00294         static inline ExternalRefCountData *create(T **ptr)
00295         {
00296 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
00297             DestroyerFn destroy = &safetyCheckDeleter;
00298 # else
00299             DestroyerFn destroy = &deleter;
00300 # endif
00301             ExternalRefCountWithContiguousData *d =
00302                 static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
00303 
00304             // initialize the d-pointer sub-object
00305             // leave d->data uninitialized
00306             new (d) Parent(destroy); // can't throw
00307 
00308             *ptr = &d->data;
00309             return d;
00310         }
00311 
00312     private:
00313         // prevent construction and the emission of virtual symbols
00314         ExternalRefCountWithContiguousData();
00315         ~ExternalRefCountWithContiguousData();
00316     };
00317 
00318     // This is the main body of QSharedPointer. It implements the
00319     // external reference counting functionality.
00320     template <class T>
00321     class ExternalRefCount: public Basic<T>
00322     {
00323     protected:
00324         typedef ExternalRefCountData Data;
00325 
00326         inline void ref() const { d->weakref.ref(); d->strongref.ref(); }
00327         inline void deref()
00328         { deref(d, this->value); }
00329         static inline void deref(Data *d, T *value)
00330         {
00331             if (!d) return;
00332             if (!d->strongref.deref()) {
00333                 if (!d->destroy())
00334                     delete value;
00335             }
00336             if (!d->weakref.deref())
00337                 delete d;
00338         }
00339 
00340         inline void internalConstruct(T *ptr)
00341         {
00342 #ifdef QT_SHAREDPOINTER_TRACK_POINTERS
00343             internalConstruct<void (*)(T *)>(ptr, normalDeleter);
00344 #else
00345             if (ptr)
00346                 d = new Data;
00347             else
00348                 d = 0;
00349             internalFinishConstruction(ptr);
00350 #endif
00351         }
00352 
00353         template <typename Deleter>
00354         inline void internalConstruct(T *ptr, Deleter deleter)
00355         {
00356             if (ptr)
00357                 d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter);
00358             else
00359                 d = 0;
00360             internalFinishConstruction(ptr);
00361         }
00362 
00363         inline void internalCreate()
00364         {
00365             T *ptr;
00366             d = ExternalRefCountWithContiguousData<T>::create(&ptr);
00367             Basic<T>::internalConstruct(ptr);
00368         }
00369 
00370         inline void internalFinishConstruction(T *ptr)
00371         {
00372             Basic<T>::internalConstruct(ptr);
00373             if (ptr) d->setQObjectShared(ptr, true);
00374 #ifdef QT_SHAREDPOINTER_TRACK_POINTERS
00375             if (ptr) internalSafetyCheckAdd2(d, ptr);
00376 #endif
00377         }
00378 
00379         inline ExternalRefCount() : d(0) { }
00380         inline ExternalRefCount(Qt::Initialization i) : Basic<T>(i) { }
00381         inline ExternalRefCount(const ExternalRefCount<T> &other) : Basic<T>(other), d(other.d)
00382         { if (d) ref(); }
00383         template <class X>
00384         inline ExternalRefCount(const ExternalRefCount<X> &other) : Basic<T>(other.value), d(other.d)
00385         { if (d) ref(); }
00386         inline ~ExternalRefCount() { deref(); }
00387 
00388         template <class X>
00389         inline void internalCopy(const ExternalRefCount<X> &other)
00390         {
00391             internalSet(other.d, other.data());
00392         }
00393 
00394         inline void internalSwap(ExternalRefCount &other)
00395         {
00396             qSwap(d, other.d);
00397             qSwap(this->value, other.value);
00398         }
00399 
00400 #if defined(Q_NO_TEMPLATE_FRIENDS)
00401     public:
00402 #else
00403         template <class X> friend class ExternalRefCount;
00404         template <class X> friend class QT_PREPEND_NAMESPACE(QWeakPointer);
00405         template <class X, class Y> friend QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
00406 #endif
00407 
00408         inline void internalSet(Data *o, T *actual)
00409         {
00410             if (o) {
00411                 // increase the strongref, but never up from zero
00412                 // or less (-1 is used by QWeakPointer on untracked QObject)
00413                 register int tmp = o->strongref;
00414                 while (tmp > 0) {
00415                     // try to increment from "tmp" to "tmp + 1"
00416                     if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
00417                         break;   // succeeded
00418                     tmp = o->strongref;  // failed, try again
00419                 }
00420 
00421                 if (tmp > 0)
00422                     o->weakref.ref();
00423                 else
00424                     o = 0;
00425             }
00426 
00427             qSwap(d, o);
00428             qSwap(this->value, actual);
00429             if (!d || d->strongref == 0)
00430                 this->value = 0;
00431 
00432             // dereference saved data
00433             deref(o, actual);
00434         }
00435 
00436         Data *d;
00437 
00438     private:
00439         template<class X> ExternalRefCount(const InternalRefCount<X> &);
00440     };
00441 } // namespace QtSharedPointer
00442 
00443 template <class T>
00444 class QSharedPointer: public QtSharedPointer::ExternalRefCount<T>
00445 {
00446     typedef typename QtSharedPointer::ExternalRefCount<T> BaseClass;
00447 public:
00448     inline QSharedPointer() { }
00449     // inline ~QSharedPointer() { }
00450 
00451     inline explicit QSharedPointer(T *ptr) : BaseClass(Qt::Uninitialized)
00452     { BaseClass::internalConstruct(ptr); }
00453 
00454     template <typename Deleter>
00455     inline QSharedPointer(T *ptr, Deleter d) { BaseClass::internalConstruct(ptr, d); }
00456 
00457     inline QSharedPointer(const QSharedPointer<T> &other) : BaseClass(other) { }
00458     inline QSharedPointer<T> &operator=(const QSharedPointer<T> &other)
00459     {
00460         BaseClass::internalCopy(other);
00461         return *this;
00462     }
00463 
00464     template <class X>
00465     inline QSharedPointer(const QSharedPointer<X> &other) : BaseClass(other)
00466     { }
00467 
00468     template <class X>
00469     inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other)
00470     {
00471         QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
00472         BaseClass::internalCopy(other);
00473         return *this;
00474     }
00475 
00476     template <class X>
00477     inline QSharedPointer(const QWeakPointer<X> &other) : BaseClass(Qt::Uninitialized)
00478     { this->d = 0; *this = other; }
00479 
00480     template <class X>
00481     inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
00482     { BaseClass::internalSet(other.d, other.value); return *this; }
00483 
00484     inline void swap(QSharedPointer &other)
00485     { QSharedPointer<T>::internalSwap(other); }
00486 
00487     template <class X>
00488     QSharedPointer<X> staticCast() const
00489     {
00490         return qSharedPointerCast<X, T>(*this);
00491     }
00492 
00493     template <class X>
00494     QSharedPointer<X> dynamicCast() const
00495     {
00496         return qSharedPointerDynamicCast<X, T>(*this);
00497     }
00498 
00499     template <class X>
00500     QSharedPointer<X> constCast() const
00501     {
00502         return qSharedPointerConstCast<X, T>(*this);
00503     }
00504 
00505 #ifndef QT_NO_QOBJECT
00506     template <class X>
00507     QSharedPointer<X> objectCast() const
00508     {
00509         return qSharedPointerObjectCast<X, T>(*this);
00510     }
00511 #endif
00512 
00513     inline void clear() { *this = QSharedPointer<T>(); }
00514 
00515     QWeakPointer<T> toWeakRef() const;
00516 
00517 protected:
00518     inline explicit QSharedPointer(Qt::Initialization i) : BaseClass(i) {}
00519 
00520 public:
00521     static inline QSharedPointer<T> create()
00522     {
00523         QSharedPointer<T> result(Qt::Uninitialized);
00524         result.internalCreate();
00525 
00526         // now initialize the data
00527         new (result.data()) T();
00528         result.internalFinishConstruction(result.data());
00529         return result;
00530     }
00531 };
00532 
00533 template <class T>
00534 class QWeakPointer
00535 {
00536 #ifndef Q_CC_NOKIAX86
00537     typedef T *QWeakPointer:: *RestrictedBool;
00538 #endif
00539     typedef QtSharedPointer::ExternalRefCountData Data;
00540 
00541 public:
00542     typedef T element_type;
00543     typedef T value_type;
00544     typedef value_type *pointer;
00545     typedef const value_type *const_pointer;
00546     typedef value_type &reference;
00547     typedef const value_type &const_reference;
00548     typedef qptrdiff difference_type;
00549 
00550     inline bool isNull() const { return d == 0 || d->strongref == 0 || value == 0; }
00551 #ifndef Q_CC_NOKIAX86
00552     inline operator RestrictedBool() const { return isNull() ? 0 : &QWeakPointer::value; }
00553 #else
00554     inline operator bool() const { return isNull() ? 0 : &QWeakPointer::value; }
00555 #endif
00556     inline bool operator !() const { return isNull(); }
00557     inline T *data() const { return d == 0 || d->strongref == 0 ? 0 : value; }
00558 
00559     inline QWeakPointer() : d(0), value(0) { }
00560     inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
00561 
00562 #ifndef QT_NO_QOBJECT
00563     // special constructor that is enabled only if X derives from QObject
00564     template <class X>
00565     inline QWeakPointer(X *ptr) : d(ptr ? d->getAndRef(ptr) : 0), value(ptr)
00566     { }
00567 #endif
00568     template <class X>
00569     inline QWeakPointer &operator=(X *ptr)
00570     { return *this = QWeakPointer(ptr); }
00571 
00572     inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value)
00573     { if (d) d->weakref.ref(); }
00574     inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o)
00575     {
00576         internalSet(o.d, o.value);
00577         return *this;
00578     }
00579 
00580     inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
00581     { if (d) d->weakref.ref();}
00582     inline QWeakPointer<T> &operator=(const QSharedPointer<T> &o)
00583     {
00584         internalSet(o.d, o.value);
00585         return *this;
00586     }
00587 
00588     template <class X>
00589     inline QWeakPointer(const QWeakPointer<X> &o) : d(0), value(0)
00590     { *this = o; }
00591 
00592     template <class X>
00593     inline QWeakPointer<T> &operator=(const QWeakPointer<X> &o)
00594     {
00595         // conversion between X and T could require access to the virtual table
00596         // so force the operation to go through QSharedPointer
00597         *this = o.toStrongRef();
00598         return *this;
00599     }
00600 
00601     template <class X>
00602     inline bool operator==(const QWeakPointer<X> &o) const
00603     { return d == o.d && value == static_cast<const T *>(o.value); }
00604 
00605     template <class X>
00606     inline bool operator!=(const QWeakPointer<X> &o) const
00607     { return !(*this == o); }
00608 
00609     template <class X>
00610     inline QWeakPointer(const QSharedPointer<X> &o) : d(0), value(0)
00611     { *this = o; }
00612 
00613     template <class X>
00614     inline QWeakPointer<T> &operator=(const QSharedPointer<X> &o)
00615     {
00616         QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
00617         internalSet(o.d, o.data());
00618         return *this;
00619     }
00620 
00621     template <class X>
00622     inline bool operator==(const QSharedPointer<X> &o) const
00623     { return d == o.d; }
00624 
00625     template <class X>
00626     inline bool operator!=(const QSharedPointer<X> &o) const
00627     { return !(*this == o); }
00628 
00629     inline void clear() { *this = QWeakPointer<T>(); }
00630 
00631     inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
00632 
00633 #if defined(QWEAKPOINTER_ENABLE_ARROW)
00634     inline T *operator->() const { return data(); }
00635 #endif
00636 
00637 private:
00638 
00639 #if defined(Q_NO_TEMPLATE_FRIENDS)
00640 public:
00641 #else
00642     template <class X> friend class QSharedPointer;
00643 #endif
00644 
00645     inline void internalSet(Data *o, T *actual)
00646     {
00647         if (d == o) return;
00648         if (o)
00649             o->weakref.ref();
00650         if (d && !d->weakref.deref())
00651             delete d;
00652         d = o;
00653         value = actual;
00654     }
00655 
00656     Data *d;
00657     T *value;
00658 };
00659 
00660 //
00661 // operator== and operator!=
00662 //
00663 template <class T, class X>
00664 bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
00665 {
00666     return ptr1.data() == ptr2.data();
00667 }
00668 template <class T, class X>
00669 bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
00670 {
00671     return ptr1.data() != ptr2.data();
00672 }
00673 
00674 template <class T, class X>
00675 bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
00676 {
00677     return ptr1.data() == ptr2;
00678 }
00679 template <class T, class X>
00680 bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2)
00681 {
00682     return ptr1 == ptr2.data();
00683 }
00684 template <class T, class X>
00685 bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
00686 {
00687     return !(ptr1 == ptr2);
00688 }
00689 template <class T, class X>
00690 bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2)
00691 {
00692     return !(ptr2 == ptr1);
00693 }
00694 
00695 template <class T, class X>
00696 bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
00697 {
00698     return ptr2 == ptr1;
00699 }
00700 template <class T, class X>
00701 bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
00702 {
00703     return ptr2 != ptr1;
00704 }
00705 
00706 //
00707 // operator-
00708 //
00709 template <class T, class X>
00710 Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
00711 {
00712     return ptr1.data() - ptr2.data();
00713 }
00714 template <class T, class X>
00715 Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
00716 {
00717     return ptr1.data() - ptr2;
00718 }
00719 template <class T, class X>
00720 Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
00721 {
00722     return ptr1 - ptr2.data();
00723 }
00724 
00725 //
00726 // operator<
00727 //
00728 template <class T, class X>
00729 Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
00730 {
00731     return ptr1.data() < ptr2.data();
00732 }
00733 template <class T, class X>
00734 Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
00735 {
00736     return ptr1.data() < ptr2;
00737 }
00738 template <class T, class X>
00739 Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
00740 {
00741     return ptr1 < ptr2.data();
00742 }
00743 
00744 //
00745 // qHash
00746 //
00747 template <class T> inline uint qHash(const T *key); // defined in qhash.h
00748 template <class T>
00749 Q_INLINE_TEMPLATE uint qHash(const QSharedPointer<T> &ptr)
00750 {
00751     return QT_PREPEND_NAMESPACE(qHash)<T>(ptr.data());
00752 }
00753 
00754 
00755 template <class T>
00756 Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
00757 {
00758     return QWeakPointer<T>(*this);
00759 }
00760 
00761 template <class T>
00762 inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2)
00763 {
00764     p1.swap(p2);
00765 }
00766 
00767 namespace QtSharedPointer {
00768 // helper functions:
00769     template <class X, class T>
00770     Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
00771     {
00772         QSharedPointer<X> result;
00773         result.internalSet(src.d, ptr);
00774         return result;
00775     }
00776 }
00777 
00778 // cast operators
00779 template <class X, class T>
00780 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
00781 {
00782     register X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
00783     return QtSharedPointer::copyAndSetPointer(ptr, src);
00784 }
00785 template <class X, class T>
00786 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
00787 {
00788     return qSharedPointerCast<X, T>(src.toStrongRef());
00789 }
00790 
00791 template <class X, class T>
00792 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
00793 {
00794     register X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
00795     return QtSharedPointer::copyAndSetPointer(ptr, src);
00796 }
00797 template <class X, class T>
00798 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
00799 {
00800     return qSharedPointerDynamicCast<X, T>(src.toStrongRef());
00801 }
00802 
00803 template <class X, class T>
00804 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
00805 {
00806     register X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
00807     return QtSharedPointer::copyAndSetPointer(ptr, src);
00808 }
00809 template <class X, class T>
00810 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
00811 {
00812     return qSharedPointerConstCast<X, T>(src.toStrongRef());
00813 }
00814 
00815 template <class X, class T>
00816 Q_INLINE_TEMPLATE
00817 QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
00818 {
00819     return qSharedPointerCast<X, T>(src).toWeakRef();
00820 }
00821 
00822 #ifndef QT_NO_QOBJECT
00823 template <class X, class T>
00824 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
00825 {
00826     register X *ptr = qobject_cast<X *>(src.data());
00827     return QtSharedPointer::copyAndSetPointer(ptr, src);
00828 }
00829 template <class X, class T>
00830 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
00831 {
00832     return qSharedPointerObjectCast<X>(src.toStrongRef());
00833 }
00834 
00835 template <class X, class T>
00836 inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
00837 qobject_cast(const QSharedPointer<T> &src)
00838 {
00839     return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
00840 }
00841 template <class X, class T>
00842 inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
00843 qobject_cast(const QWeakPointer<T> &src)
00844 {
00845     return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
00846 }
00847 
00848 #endif
00849 
00850 QT_END_NAMESPACE
00851 
00852 QT_END_HEADER
00853 
00854 #endif