00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00047 #ifndef BLOCXX_COW_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00048 #define BLOCXX_COW_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00049
00050 #include "blocxx/BLOCXX_config.h"
00051
00052 namespace BLOCXX_NAMESPACE
00053 {
00054
00055 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00056 namespace COWIntrusiveReferenceHelpers
00057 {
00058
00059 BLOCXX_COMMON_API void throwNULLException();
00060 inline void checkNull(const void* p)
00061 {
00062 if (p == 0)
00063 {
00064 throwNULLException();
00065 }
00066 }
00067 }
00068 #endif
00069
00088 template<class T> class COWIntrusiveReference
00089 {
00090 private:
00091 typedef COWIntrusiveReference this_type;
00092 public:
00093 typedef T element_type;
00094
00099 COWIntrusiveReference(): m_pObj(0)
00100 {
00101 }
00109 COWIntrusiveReference(T * p, bool addRef = true): m_pObj(p)
00110 {
00111 if (m_pObj != 0 && addRef) COWIntrusiveReferenceAddRef(m_pObj);
00112 }
00123 template<class U> COWIntrusiveReference(COWIntrusiveReference<U> const & rhs): m_pObj(rhs.m_pObj)
00124 {
00125 if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj);
00126 }
00135 COWIntrusiveReference(COWIntrusiveReference const & rhs): m_pObj(rhs.m_pObj)
00136 {
00137 if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj);
00138 }
00144 ~COWIntrusiveReference()
00145 {
00146 if (m_pObj != 0) COWIntrusiveReferenceRelease(m_pObj);
00147 }
00148
00160 template<class U> COWIntrusiveReference & operator=(COWIntrusiveReference<U> const & rhs)
00161 {
00162 this_type(rhs).swap(*this);
00163 return *this;
00164 }
00175 COWIntrusiveReference & operator=(COWIntrusiveReference const & rhs)
00176 {
00177 this_type(rhs).swap(*this);
00178 return *this;
00179 }
00188 COWIntrusiveReference & operator=(T * rhs)
00189 {
00190 this_type(rhs).swap(*this);
00191 return *this;
00192 }
00197 const T * getPtr() const
00198 {
00199 return m_pObj;
00200 }
00201
00206 const T & operator*() const
00207 {
00208 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00209 COWIntrusiveReferenceHelpers::checkNull(this);
00210 COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00211 #endif
00212 return *m_pObj;
00213 }
00214
00219 const T * operator->() const
00220 {
00221 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00222 COWIntrusiveReferenceHelpers::checkNull(this);
00223 COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00224 #endif
00225 return m_pObj;
00226 }
00227
00232 T & operator*()
00233 {
00234 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00235 COWIntrusiveReferenceHelpers::checkNull(this);
00236 COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00237 #endif
00238 getWriteLock();
00239 return *m_pObj;
00240 }
00241
00246 T * operator->()
00247 {
00248 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00249 COWIntrusiveReferenceHelpers::checkNull(this);
00250 COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00251 #endif
00252 getWriteLock();
00253 return m_pObj;
00254 }
00255
00256 typedef T * this_type::*unspecified_bool_type;
00257 operator unspecified_bool_type () const
00258 {
00259 return m_pObj == 0? 0: &this_type::m_pObj;
00260 }
00261
00267 bool operator! () const
00268 {
00269 return m_pObj == 0;
00270 }
00271
00272 void swap(COWIntrusiveReference & rhs)
00273 {
00274 T * tmp = m_pObj;
00275 m_pObj = rhs.m_pObj;
00276 rhs.m_pObj = tmp;
00277 }
00278
00279 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00280
00281 template <class U> friend class COWIntrusiveReference;
00282 private:
00283 #endif
00284
00290 void getWriteLock()
00291 {
00292 if ((m_pObj != 0) && !COWIntrusiveReferenceUnique(m_pObj))
00293 {
00294 m_pObj = COWIntrusiveReferenceClone(m_pObj);
00295 }
00296 }
00297
00298
00299 T * m_pObj;
00300 };
00301 template<class T, class U> inline bool operator==(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b)
00302 {
00303 return a.getPtr() == b.getPtr();
00304 }
00305 template<class T, class U> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b)
00306 {
00307 return a.getPtr() != b.getPtr();
00308 }
00309 template<class T> inline bool operator==(COWIntrusiveReference<T> const & a, const T * b)
00310 {
00311 return a.getPtr() == b;
00312 }
00313 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, const T * b)
00314 {
00315 return a.getPtr() != b;
00316 }
00317 template<class T> inline bool operator==(const T * a, COWIntrusiveReference<T> const & b)
00318 {
00319 return a == b.getPtr();
00320 }
00321 template<class T> inline bool operator!=(const T * a, COWIntrusiveReference<T> const & b)
00322 {
00323 return a != b.getPtr();
00324 }
00325 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
00326
00327 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b)
00328 {
00329 return a.getPtr() != b.getPtr();
00330 }
00331 #endif
00332 template<class T> inline bool operator<(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b)
00333 {
00334 return a.getPtr() < b.getPtr();
00335 }
00336 template<class T> void swap(COWIntrusiveReference<T> & lhs, COWIntrusiveReference<T> & rhs)
00337 {
00338 lhs.swap(rhs);
00339 }
00340
00341 }
00342
00343 #endif
00344