Home · All Classes · All Namespaces · Modules · Functions · Files
shared-ptr.h
00001 
00023 #ifndef _TelepathyQt_shared_ptr_h_HEADER_GUARD_
00024 #define _TelepathyQt_shared_ptr_h_HEADER_GUARD_
00025 
00026 #ifndef IN_TP_QT_HEADER
00027 #error IN_TP_QT_HEADER
00028 #endif
00029 
00030 #include <TelepathyQt/Global>
00031 
00032 #include <QHash>
00033 #include <QObject>
00034 
00035 namespace Tp
00036 {
00037 
00038 class RefCounted;
00039 template <class T> class SharedPtr;
00040 template <class T> class WeakPtr;
00041 
00042 class TP_QT_EXPORT RefCounted
00043 {
00044     Q_DISABLE_COPY(RefCounted)
00045 
00046     class SharedCount
00047     {
00048         Q_DISABLE_COPY(SharedCount)
00049 
00050     public:
00051         SharedCount(RefCounted *d)
00052             : d(d), strongref(0), weakref(0)
00053         {
00054         }
00055 
00056     private:
00057         template <class T> friend class SharedPtr;
00058         template <class T> friend class WeakPtr;
00059         friend class RefCounted;
00060 
00061         RefCounted *d;
00062         mutable QAtomicInt strongref;
00063         mutable QAtomicInt weakref;
00064     };
00065 
00066 public:
00067     inline RefCounted() : sc(new SharedCount(this))
00068     {
00069         sc->weakref.ref();
00070     }
00071 
00072     inline virtual ~RefCounted()
00073     {
00074         sc->d = 0;
00075         if (!sc->weakref.deref()) {
00076             delete sc;
00077         }
00078     }
00079 
00080 private:
00081     template <class T> friend class SharedPtr;
00082     template <class T> friend class WeakPtr;
00083     // TODO: Remove when Conn.I.ContactList, etc becomes mandatory. This is required to circumvent
00084     //       a reference cycle when using contact list channels, due to the fact that Channels hold
00085     //       strong references to their parent Connection, but not needed when using
00086     //       Conn.I.ContactList and friends.
00087     friend class ContactManager;
00088 
00089     inline void ref() const { sc->strongref.ref(); }
00090     inline bool deref() const { return sc->strongref.deref(); }
00091 
00092     SharedCount *sc;
00093 };
00094 
00095 template <class T>
00096 class SharedPtr
00097 {
00098     typedef bool (SharedPtr<T>::*UnspecifiedBoolType)() const;
00099 
00100 public:
00101     inline SharedPtr() : d(0) { }
00102     explicit inline SharedPtr(T *d) : d(d) { if (d) { d->ref(); } }
00103     template <typename Subclass>
00104         inline SharedPtr(const SharedPtr<Subclass> &o) : d(o.data()) { if (d) { d->ref(); } }
00105     inline SharedPtr(const SharedPtr<T> &o) : d(o.d) { if (d) { d->ref(); } }
00106     explicit inline SharedPtr(const WeakPtr<T> &o)
00107     {
00108         RefCounted::SharedCount *sc = o.sc;
00109         if (sc) {
00110             // increase the strongref, but never up from zero
00111             // or less (negative is used on untracked objects)
00112             register int tmp = sc->strongref.fetchAndAddOrdered(0);
00113             while (tmp > 0) {
00114                 // try to increment from "tmp" to "tmp + 1"
00115                 if (sc->strongref.testAndSetRelaxed(tmp, tmp + 1)) {
00116                     // succeeded
00117                     break;
00118                 }
00119                 // failed, try again
00120                 tmp = sc->strongref.fetchAndAddOrdered(0);
00121             }
00122 
00123             if (tmp > 0) {
00124                 d = dynamic_cast<T*>(sc->d);
00125                 Q_ASSERT(d != NULL);
00126             } else {
00127                 d = 0;
00128             }
00129         } else {
00130             d = 0;
00131         }
00132     }
00133 
00134     inline ~SharedPtr()
00135     {
00136         if (d && !d->deref()) {
00137             T *saved = d;
00138             d = 0;
00139             delete saved;
00140         }
00141     }
00142 
00143     inline void reset()
00144     {
00145         SharedPtr<T>().swap(*this);
00146     }
00147 
00148     inline T *data() const { return d; }
00149     inline const T *constData() const { return d; }
00150     inline T *operator->() { return d; }
00151     inline T *operator->() const { return d; }
00152 
00153     inline bool isNull() const { return !d; }
00154     inline bool operator!() const { return isNull(); }
00155     operator UnspecifiedBoolType() const { return !isNull() ? &SharedPtr<T>::operator! : 0; }
00156 
00157     inline bool operator==(const SharedPtr<T> &o) const { return d == o.d; }
00158     inline bool operator!=(const SharedPtr<T> &o) const { return d != o.d; }
00159     inline bool operator==(const T *ptr) const { return d == ptr; }
00160     inline bool operator!=(const T *ptr) const { return d != ptr; }
00161 
00162     inline SharedPtr<T> &operator=(const SharedPtr<T> &o)
00163     {
00164         SharedPtr<T>(o).swap(*this);
00165         return *this;
00166     }
00167 
00168     inline void swap(SharedPtr<T> &o)
00169     {
00170         T *tmp = d;
00171         d = o.d;
00172         o.d = tmp;
00173     }
00174 
00175     template <class X>
00176     static inline SharedPtr<T> staticCast(const SharedPtr<X> &src)
00177     {
00178         return SharedPtr<T>(static_cast<T*>(src.data()));
00179     }
00180 
00181     template <class X>
00182     static inline SharedPtr<T> dynamicCast(const SharedPtr<X> &src)
00183     {
00184         return SharedPtr<T>(dynamic_cast<T*>(src.data()));
00185     }
00186 
00187     template <class X>
00188     static inline SharedPtr<T> constCast(const SharedPtr<X> &src)
00189     {
00190         return SharedPtr<T>(const_cast<T*>(src.data()));
00191     }
00192 
00193     template <class X>
00194     static inline SharedPtr<T> qObjectCast(const SharedPtr<X> &src)
00195     {
00196         return SharedPtr<T>(qobject_cast<T*>(src.data()));
00197     }
00198 
00199 private:
00200     friend class WeakPtr<T>;
00201 
00202     T *d;
00203 };
00204 
00205 template<typename T>
00206 inline uint qHash(const SharedPtr<T> &ptr)
00207 {
00208     return QT_PREPEND_NAMESPACE(qHash<T>(ptr.data()));
00209 }
00210 
00211 template<typename T> inline uint qHash(const WeakPtr<T> &ptr);
00212 
00213 template <class T>
00214 class WeakPtr
00215 {
00216     typedef bool (WeakPtr<T>::*UnspecifiedBoolType)() const;
00217 
00218 public:
00219     inline WeakPtr() : sc(0) { }
00220     explicit inline WeakPtr(T *d)
00221     {
00222         if (d) {
00223             sc = d->sc;
00224             sc->weakref.ref();
00225         } else {
00226             sc = 0;
00227         }
00228     }
00229     inline WeakPtr(const WeakPtr<T> &o) : sc(o.sc) { if (sc) { sc->weakref.ref(); } }
00230     inline WeakPtr(const SharedPtr<T> &o)
00231     {
00232         if (o.d) {
00233             sc = o.d->sc;
00234             sc->weakref.ref();
00235         } else {
00236             sc = 0;
00237         }
00238     }
00239     inline ~WeakPtr()
00240     {
00241         if (sc && !sc->weakref.deref()) {
00242             delete sc;
00243         }
00244     }
00245 
00246     inline bool isNull() const { return !sc || sc->strongref.fetchAndAddOrdered(0) <= 0; }
00247     inline bool operator!() const { return isNull(); }
00248     operator UnspecifiedBoolType() const { return !isNull() ? &WeakPtr<T>::operator! : 0; }
00249 
00250     inline WeakPtr<T> &operator=(const WeakPtr<T> &o)
00251     {
00252         WeakPtr<T>(o).swap(*this);
00253         return *this;
00254     }
00255 
00256     inline WeakPtr<T> &operator=(const SharedPtr<T> &o)
00257     {
00258         WeakPtr<T>(o).swap(*this);
00259         return *this;
00260     }
00261 
00262     inline void swap(WeakPtr<T> &o)
00263     {
00264         RefCounted::SharedCount *tmp = sc;
00265         sc = o.sc;
00266         o.sc = tmp;
00267     }
00268 
00269     SharedPtr<T> toStrongRef() const { return SharedPtr<T>(*this); }
00270 
00271 private:
00272     friend class SharedPtr<T>;
00273     friend uint qHash<T>(const WeakPtr<T> &ptr);
00274 
00275     RefCounted::SharedCount *sc;
00276 };
00277 
00278 template<typename T>
00279 inline uint qHash(const WeakPtr<T> &ptr)
00280 {
00281     T *actualPtr = ptr.sc ? ptr.sc.d : 0;
00282     return QT_PREPEND_NAMESPACE(qHash<T>(actualPtr));
00283 }
00284 
00285 } // Tp
00286 
00287 #endif


Copyright © 2008-2011 Collabora Ltd. and Nokia Corporation
Telepathy-Qt 0.9.3