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
00037 #ifndef BLOCXX_COWREFERENCE_HPP_INCLUDE_GUARD_
00038 #define BLOCXX_COWREFERENCE_HPP_INCLUDE_GUARD_
00039 #include "blocxx/BLOCXX_config.h"
00040 #include "blocxx/COWReferenceBase.hpp"
00041
00042 namespace BLOCXX_NAMESPACE
00043 {
00044
00050 template<class T>
00051 class COWReference : private COWReferenceBase
00052 {
00053 public:
00054 typedef T element_type;
00055
00060 COWReference();
00061
00066 explicit COWReference(T* ptr);
00067
00074 COWReference(const COWReference<T>& arg);
00075
00083 template <class U>
00084 COWReference(const COWReference<U>& arg);
00085
00091 ~COWReference();
00092
00101 COWReference<T>& operator= (const COWReference<T>& arg);
00102
00112 COWReference<T>& operator= (T* newObj);
00113
00114 void swap(COWReference<T>& arg);
00115
00119 T* operator->();
00120
00124 const T* operator->() const;
00125
00129 T& operator*();
00130
00134 const T& operator*() const;
00135
00139 const T* getPtr() const;
00140
00141 typedef T* volatile COWReference::*safe_bool;
00142 operator safe_bool () const
00143 {
00144 return m_pObj ? &COWReference::m_pObj : 0;
00145 }
00146
00152 bool operator!() const
00153 {
00154 return !m_pObj;
00155 }
00156
00157 template <class U>
00158 COWReference<U> cast_to() const;
00159
00160 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00161
00162 template <class U> friend class COWReference;
00163 private:
00164 #endif
00165 T* volatile m_pObj;
00166 void decRef();
00167 void getWriteLock();
00168 };
00169
00171 template<class T>
00172 inline COWReference<T>::COWReference()
00173 : COWReferenceBase(), m_pObj(0)
00174 {
00175 }
00177 template<class T>
00178 inline COWReference<T>::COWReference(T* ptr)
00179 : COWReferenceBase(), m_pObj(ptr)
00180 {
00181 }
00183 template<class T>
00184 inline COWReference<T>::COWReference(const COWReference<T>& arg)
00185 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00186 {
00187 }
00189 template<class T>
00190 template<class U>
00191 inline COWReference<T>::COWReference(const COWReference<U>& arg)
00192 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00193 {
00194 }
00196 template<class T>
00197 inline COWReference<T>::~COWReference()
00198 {
00199 try
00200 {
00201 decRef();
00202 }
00203 catch (...)
00204 {
00205
00206 }
00207 }
00209 template<class T>
00210 inline void COWReference<T>::decRef()
00211 {
00212 typedef char type_must_be_complete[sizeof(T)];
00213 if (COWReferenceBase::decRef())
00214 {
00215 delete m_pObj;
00216 m_pObj = 0;
00217 }
00218 }
00219
00221 template<class T>
00222 inline void COWReference<T>::getWriteLock()
00223 {
00224 if (COWReferenceBase::refCountGreaterThanOne())
00225 {
00226
00227
00228 T* tmp = COWReferenceClone(m_pObj);
00229
00230 if (COWReferenceBase::getWriteLock())
00231 {
00232 delete tmp;
00233 }
00234 else
00235 {
00236 m_pObj = tmp;
00237 }
00238 }
00239 }
00241 template<class T>
00242 inline COWReference<T>& COWReference<T>::operator= (const COWReference<T>& arg)
00243 {
00244 COWReference<T>(arg).swap(*this);
00245 return *this;
00246 }
00248 template<class T>
00249 inline COWReference<T>& COWReference<T>::operator= (T* newObj)
00250 {
00251 COWReference<T>(newObj).swap(*this);
00252 return *this;
00253 }
00255 template <class T>
00256 inline void COWReference<T>::swap(COWReference<T>& arg)
00257 {
00258 COWReferenceBase::swap(arg);
00259 COWRefSwap(m_pObj, arg.m_pObj);
00260 }
00262 template<class T>
00263 inline T* COWReference<T>::operator->()
00264 {
00265 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00266 checkNull(this);
00267 checkNull(m_pObj);
00268 #endif
00269 getWriteLock();
00270
00271 return m_pObj;
00272 }
00274 template<class T>
00275 inline T& COWReference<T>::operator*()
00276 {
00277 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00278 checkNull(this);
00279 checkNull(m_pObj);
00280 #endif
00281 getWriteLock();
00282
00283 return *(m_pObj);
00284 }
00286 template<class T>
00287 inline const T* COWReference<T>::operator->() const
00288 {
00289 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00290 checkNull(this);
00291 checkNull(m_pObj);
00292 #endif
00293
00294 return m_pObj;
00295 }
00297 template<class T>
00298 inline const T& COWReference<T>::operator*() const
00299 {
00300 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00301 checkNull(this);
00302 checkNull(m_pObj);
00303 #endif
00304
00305 return *(m_pObj);
00306 }
00308 template<class T>
00309 inline const T* COWReference<T>::getPtr() const
00310 {
00311 return m_pObj;
00312 }
00314 template <class T>
00315 template <class U>
00316 inline COWReference<U>
00317 COWReference<T>::cast_to() const
00318 {
00319 COWReference<U> rval;
00320 rval.m_pObj = dynamic_cast<U*>(m_pObj);
00321 if (rval.m_pObj)
00322 {
00323 rval.useRefCountOf(*this);
00324 rval.incRef();
00325 }
00326 return rval;
00327 }
00329
00330 template <class T, class U>
00331 inline bool operator==(const COWReference<T>& a, const COWReference<U>& b)
00332 {
00333 return a.getPtr() == b.getPtr();
00334 }
00336 template <class T, class U>
00337 inline bool operator!=(const COWReference<T>& a, const COWReference<U>& b)
00338 {
00339 return a.getPtr() != b.getPtr();
00340 }
00342 template <class T, class U>
00343 inline bool operator<(const COWReference<T>& a, const COWReference<U>& b)
00344 {
00345 return a.getPtr() < b.getPtr();
00346 }
00347
00349 template <class T>
00350 inline T* COWReferenceClone(T* obj)
00351 {
00352
00353
00354 return obj->clone();
00355 }
00356
00357 }
00358
00359 #endif // BLOCXX_COWREFERENCE_HPP_