| 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