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 template <class U>
00161 void useRefCountOf(const COWReference<U>&);
00162
00163 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00164
00165 template <class U> friend class COWReference;
00166 private:
00167 #endif
00168 T* volatile m_pObj;
00169 void decRef();
00170 void getWriteLock();
00171 };
00172
00174 template<class T>
00175 inline COWReference<T>::COWReference()
00176 : COWReferenceBase(), m_pObj(0)
00177 {
00178 }
00180 template<class T>
00181 inline COWReference<T>::COWReference(T* ptr)
00182 : COWReferenceBase(), m_pObj(ptr)
00183 {
00184 }
00186 template<class T>
00187 inline COWReference<T>::COWReference(const COWReference<T>& arg)
00188 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00189 {
00190 }
00192 template<class T>
00193 template<class U>
00194 inline COWReference<T>::COWReference(const COWReference<U>& arg)
00195 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00196 {
00197 }
00199 template<class T>
00200 inline COWReference<T>::~COWReference()
00201 {
00202 try
00203 {
00204 decRef();
00205 }
00206 catch (...)
00207 {
00208
00209 }
00210 }
00212 template<class T>
00213 inline void COWReference<T>::decRef()
00214 {
00215 typedef char type_must_be_complete[sizeof(T)];
00216 if (COWReferenceBase::decRef())
00217 {
00218 delete m_pObj;
00219 m_pObj = 0;
00220 }
00221 }
00222
00224 template<class T>
00225 inline void COWReference<T>::getWriteLock()
00226 {
00227 if (COWReferenceBase::refCountGreaterThanOne())
00228 {
00229
00230
00231 T* tmp = COWReferenceClone(m_pObj);
00232
00233 if (COWReferenceBase::getWriteLock())
00234 {
00235 delete tmp;
00236 }
00237 else
00238 {
00239 m_pObj = tmp;
00240 }
00241 }
00242 }
00244 template<class T>
00245 inline COWReference<T>& COWReference<T>::operator= (const COWReference<T>& arg)
00246 {
00247 COWReference<T>(arg).swap(*this);
00248 return *this;
00249 }
00251 template<class T>
00252 inline COWReference<T>& COWReference<T>::operator= (T* newObj)
00253 {
00254 COWReference<T>(newObj).swap(*this);
00255 return *this;
00256 }
00258 template <class T>
00259 inline void COWReference<T>::swap(COWReference<T>& arg)
00260 {
00261 COWReferenceBase::swap(arg);
00262 COWRefSwap(m_pObj, arg.m_pObj);
00263 }
00265 template<class T>
00266 inline T* COWReference<T>::operator->()
00267 {
00268 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00269 checkNull(this);
00270 checkNull(m_pObj);
00271 #endif
00272 getWriteLock();
00273
00274 return m_pObj;
00275 }
00277 template<class T>
00278 inline T& COWReference<T>::operator*()
00279 {
00280 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00281 checkNull(this);
00282 checkNull(m_pObj);
00283 #endif
00284 getWriteLock();
00285
00286 return *(m_pObj);
00287 }
00289 template<class T>
00290 inline const T* COWReference<T>::operator->() const
00291 {
00292 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00293 checkNull(this);
00294 checkNull(m_pObj);
00295 #endif
00296
00297 return m_pObj;
00298 }
00300 template<class T>
00301 inline const T& COWReference<T>::operator*() const
00302 {
00303 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00304 checkNull(this);
00305 checkNull(m_pObj);
00306 #endif
00307
00308 return *(m_pObj);
00309 }
00311 template<class T>
00312 inline const T* COWReference<T>::getPtr() const
00313 {
00314 return m_pObj;
00315 }
00317 template <class T>
00318 template <class U>
00319 inline COWReference<U>
00320 COWReference<T>::cast_to() const
00321 {
00322 COWReference<U> rval;
00323 rval.m_pObj = dynamic_cast<U*>(m_pObj);
00324 if (rval.m_pObj)
00325 {
00326 rval.useRefCountOf(*this);
00327 }
00328 return rval;
00329 }
00331 template <class T>
00332 template <class U>
00333 inline void
00334 COWReference<T>::useRefCountOf(const COWReference<U>& arg)
00335 {
00336 COWReferenceBase::useRefCountOf(arg);
00337 }
00339
00340 template <class T, class U>
00341 inline bool operator==(const COWReference<T>& a, const COWReference<U>& b)
00342 {
00343 return a.getPtr() == b.getPtr();
00344 }
00346 template <class T, class U>
00347 inline bool operator!=(const COWReference<T>& a, const COWReference<U>& b)
00348 {
00349 return a.getPtr() != b.getPtr();
00350 }
00352 template <class T, class U>
00353 inline bool operator<(const COWReference<T>& a, const COWReference<U>& b)
00354 {
00355 return a.getPtr() < b.getPtr();
00356 }
00357
00359 template <class T>
00360 inline T* COWReferenceClone(T* obj)
00361 {
00362
00363
00364 return obj->clone();
00365 }
00366
00367 }
00368
00369 #endif // BLOCXX_COWREFERENCE_HPP_