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
00084
00085
00086
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
00111
00112 register int tmp = sc->strongref.fetchAndAddOrdered(0);
00113 while (tmp > 0) {
00114
00115 if (sc->strongref.testAndSetRelaxed(tmp, tmp + 1)) {
00116
00117 break;
00118 }
00119
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 }
00286
00287 #endif