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
00045 #ifndef OWBI1_COWBI1_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00046 #define OWBI1_COWBI1_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00047
00048 #include "OWBI1_config.h"
00049
00050 namespace OWBI1
00051 {
00052
00053 #ifdef OWBI1_CHECK_NULL_REFERENCES
00054 namespace COWIntrusiveReferenceHelpers
00055 {
00056
00057 OWBI1_OWBI1PROVIFC_API void throwNULLException();
00058 inline void checkNull(const void* p)
00059 {
00060 if (p == 0)
00061 {
00062 throwNULLException();
00063 }
00064 }
00065 }
00066 #endif
00067
00089 template<class T> class COWIntrusiveReference
00090 {
00091 private:
00092 typedef COWIntrusiveReference this_type;
00093 public:
00094 typedef T element_type;
00095
00096 COWIntrusiveReference(): m_pObj(0)
00097 {
00098 }
00099 COWIntrusiveReference(T * p, bool addRef = true): m_pObj(p)
00100 {
00101 if (m_pObj != 0 && addRef) COWIntrusiveReferenceAddRef(m_pObj);
00102 }
00103 template<class U> COWIntrusiveReference(COWIntrusiveReference<U> const & rhs): m_pObj(rhs.m_pObj)
00104 {
00105 if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj);
00106 }
00107 COWIntrusiveReference(COWIntrusiveReference const & rhs): m_pObj(rhs.m_pObj)
00108 {
00109 if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj);
00110 }
00111 ~COWIntrusiveReference()
00112 {
00113 if (m_pObj != 0) COWIntrusiveReferenceRelease(m_pObj);
00114 }
00115 template<class U> COWIntrusiveReference & operator=(COWIntrusiveReference<U> const & rhs)
00116 {
00117 this_type(rhs).swap(*this);
00118 return *this;
00119 }
00120 COWIntrusiveReference & operator=(COWIntrusiveReference const & rhs)
00121 {
00122 this_type(rhs).swap(*this);
00123 return *this;
00124 }
00125 COWIntrusiveReference & operator=(T * rhs)
00126 {
00127 this_type(rhs).swap(*this);
00128 return *this;
00129 }
00130 const T * getPtr() const
00131 {
00132 return m_pObj;
00133 }
00134
00135 const T & operator*() const
00136 {
00137 #ifdef OWBI1_CHECK_NULL_REFERENCES
00138 COWIntrusiveReferenceHelpers::checkNull(this);
00139 COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00140 #endif
00141 return *m_pObj;
00142 }
00143
00144 const T * operator->() const
00145 {
00146 #ifdef OWBI1_CHECK_NULL_REFERENCES
00147 COWIntrusiveReferenceHelpers::checkNull(this);
00148 COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00149 #endif
00150 return m_pObj;
00151 }
00152
00153 T & operator*()
00154 {
00155 #ifdef OWBI1_CHECK_NULL_REFERENCES
00156 COWIntrusiveReferenceHelpers::checkNull(this);
00157 COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00158 #endif
00159 getWriteLock();
00160 return *m_pObj;
00161 }
00162
00163 T * operator->()
00164 {
00165 #ifdef OWBI1_CHECK_NULL_REFERENCES
00166 COWIntrusiveReferenceHelpers::checkNull(this);
00167 COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00168 #endif
00169 getWriteLock();
00170 return m_pObj;
00171 }
00172
00173 typedef T * this_type::*unspecified_bool_type;
00174 operator unspecified_bool_type () const
00175 {
00176 return m_pObj == 0? 0: &this_type::m_pObj;
00177 }
00178
00179 bool operator! () const
00180 {
00181 return m_pObj == 0;
00182 }
00183
00184 void swap(COWIntrusiveReference & rhs)
00185 {
00186 T * tmp = m_pObj;
00187 m_pObj = rhs.m_pObj;
00188 rhs.m_pObj = tmp;
00189 }
00190
00191 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00192
00193 template <class U> friend class COWIntrusiveReference;
00194 private:
00195 #endif
00196
00197 void getWriteLock()
00198 {
00199 if ((m_pObj != 0) && !COWIntrusiveReferenceUnique(m_pObj))
00200 {
00201 m_pObj = COWIntrusiveReferenceClone(m_pObj);
00202 }
00203 }
00204
00205
00206 T * m_pObj;
00207 };
00208 template<class T, class U> inline bool operator==(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b)
00209 {
00210 return a.getPtr() == b.getPtr();
00211 }
00212 template<class T, class U> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b)
00213 {
00214 return a.getPtr() != b.getPtr();
00215 }
00216 template<class T> inline bool operator==(COWIntrusiveReference<T> const & a, const T * b)
00217 {
00218 return a.getPtr() == b;
00219 }
00220 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, const T * b)
00221 {
00222 return a.getPtr() != b;
00223 }
00224 template<class T> inline bool operator==(const T * a, COWIntrusiveReference<T> const & b)
00225 {
00226 return a == b.getPtr();
00227 }
00228 template<class T> inline bool operator!=(const T * a, COWIntrusiveReference<T> const & b)
00229 {
00230 return a != b.getPtr();
00231 }
00232 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
00233
00234 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b)
00235 {
00236 return a.getPtr() != b.getPtr();
00237 }
00238 #endif
00239 template<class T> inline bool operator<(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b)
00240 {
00241 return a.getPtr() < b.getPtr();
00242 }
00243 template<class T> void swap(COWIntrusiveReference<T> & lhs, COWIntrusiveReference<T> & rhs)
00244 {
00245 lhs.swap(rhs);
00246 }
00247
00248 }
00249
00250 #endif
00251