Home · All Classes · All Namespaces · Modules · Functions · Files |
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.1 |