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
00038 #ifndef BLOCXX_COWREFERENCE_HPP_INCLUDE_GUARD_
00039 #define BLOCXX_COWREFERENCE_HPP_INCLUDE_GUARD_
00040 #include "blocxx/BLOCXX_config.h"
00041 #include "blocxx/COWReferenceBase.hpp"
00042 #include "blocxx/ReferenceHelpers.hpp"
00043 #include "blocxx/SafeBool.hpp"
00044
00045 namespace BLOCXX_NAMESPACE
00046 {
00047
00053 template<class T>
00054 class COWReference : private COWReferenceBase
00055 {
00056 public:
00057 typedef T element_type;
00058
00063 COWReference();
00064
00069 explicit COWReference(T* ptr);
00070
00077 COWReference(const COWReference<T>& arg);
00078
00086 template <class U>
00087 COWReference(const COWReference<U>& arg);
00088
00094 ~COWReference();
00095
00104 COWReference<T>& operator= (const COWReference<T>& arg);
00105
00115 COWReference<T>& operator= (T* newObj);
00116
00117 void swap(COWReference<T>& arg);
00118
00122 T* operator->();
00123
00127 const T* operator->() const;
00128
00132 T& operator*();
00133
00137 const T& operator*() const;
00138
00142 const T* getPtr() const;
00143 bool isNull() const BLOCXX_DEPRECATED;
00144
00145 BLOCXX_SAFE_BOOL_IMPL(COWReference, T* volatile, COWReference::m_pObj, m_pObj)
00146
00147 template <class U>
00148 COWReference<U> cast_to() const;
00149
00150 template <class U>
00151 void useRefCountOf(const COWReference<U>&);
00152
00153 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00154
00155 template <class U> friend class COWReference;
00156 private:
00157 #endif
00158 T* volatile m_pObj;
00159 void decRef();
00160 void getWriteLock();
00161 };
00163 template<class T>
00164 inline COWReference<T>::COWReference()
00165 : COWReferenceBase(), m_pObj(0)
00166 {
00167 }
00169 template<class T>
00170 inline COWReference<T>::COWReference(T* ptr)
00171 : COWReferenceBase(), m_pObj(ptr)
00172 {
00173 }
00175 template<class T>
00176 inline COWReference<T>::COWReference(const COWReference<T>& arg)
00177 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00178 {
00179 }
00181 template<class T>
00182 template<class U>
00183 inline COWReference<T>::COWReference(const COWReference<U>& arg)
00184 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00185 {
00186 }
00188 template<class T>
00189 inline COWReference<T>::~COWReference()
00190 {
00191 try
00192 {
00193 decRef();
00194 }
00195 catch (...)
00196 {
00197
00198 }
00199 }
00201 template<class T>
00202 inline void COWReference<T>::decRef()
00203 {
00204 typedef char type_must_be_complete[sizeof(T)];
00205 if (COWReferenceBase::decRef())
00206 {
00207 delete m_pObj;
00208 m_pObj = 0;
00209 }
00210 }
00211
00213 template<class T>
00214 inline void COWReference<T>::getWriteLock()
00215 {
00216 if (COWReferenceBase::refCountGreaterThanOne())
00217 {
00218
00219
00220 T* tmp = COWReferenceClone(m_pObj);
00221
00222 if (COWReferenceBase::getWriteLock())
00223 {
00224 delete tmp;
00225 }
00226 else
00227 {
00228 m_pObj = tmp;
00229 }
00230 }
00231 }
00233 template<class T>
00234 inline COWReference<T>& COWReference<T>::operator= (const COWReference<T>& arg)
00235 {
00236 COWReference<T>(arg).swap(*this);
00237 return *this;
00238 }
00240 template<class T>
00241 inline COWReference<T>& COWReference<T>::operator= (T* newObj)
00242 {
00243 COWReference<T>(newObj).swap(*this);
00244 return *this;
00245 }
00247 template <class T>
00248 inline void COWReference<T>::swap(COWReference<T>& arg)
00249 {
00250 COWReferenceBase::swap(arg);
00251 COWRefSwap(m_pObj, arg.m_pObj);
00252 }
00254 template<class T>
00255 inline T* COWReference<T>::operator->()
00256 {
00257 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00258 ReferenceHelpers::checkNull(this);
00259 ReferenceHelpers::checkNull(m_pObj);
00260 #endif
00261 getWriteLock();
00262
00263 return m_pObj;
00264 }
00266 template<class T>
00267 inline T& COWReference<T>::operator*()
00268 {
00269 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00270 ReferenceHelpers::checkNull(this);
00271 ReferenceHelpers::checkNull(m_pObj);
00272 #endif
00273 getWriteLock();
00274
00275 return *(m_pObj);
00276 }
00278 template<class T>
00279 inline const T* COWReference<T>::operator->() const
00280 {
00281 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00282 ReferenceHelpers::checkNull(this);
00283 ReferenceHelpers::checkNull(m_pObj);
00284 #endif
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 ReferenceHelpers::checkNull(this);
00294 ReferenceHelpers::checkNull(m_pObj);
00295 #endif
00296
00297 return *(m_pObj);
00298 }
00300 template<class T>
00301 inline const T* COWReference<T>::getPtr() const
00302 {
00303 return m_pObj;
00304 }
00306 template<class T>
00307 inline bool COWReference<T>::isNull() const
00308 {
00309 return (m_pObj == 0);
00310 }
00312 template <class T>
00313 template <class U>
00314 inline COWReference<U>
00315 COWReference<T>::cast_to() const
00316 {
00317 COWReference<U> rval;
00318 rval.m_pObj = dynamic_cast<U*>(m_pObj);
00319 if (rval.m_pObj)
00320 {
00321 rval.useRefCountOf(*this);
00322 }
00323 return rval;
00324 }
00326 template <class T>
00327 template <class U>
00328 inline void
00329 COWReference<T>::useRefCountOf(const COWReference<U>& arg)
00330 {
00331 COWReferenceBase::useRefCountOf(arg);
00332 }
00334
00335 template <class T, class U>
00336 inline bool operator==(const COWReference<T>& a, const COWReference<U>& b)
00337 {
00338 return a.getPtr() == b.getPtr();
00339 }
00341 template <class T, class U>
00342 inline bool operator!=(const COWReference<T>& a, const COWReference<U>& b)
00343 {
00344 return a.getPtr() != b.getPtr();
00345 }
00347 template <class T, class U>
00348 inline bool operator<(const COWReference<T>& a, const COWReference<U>& b)
00349 {
00350 return a.getPtr() < b.getPtr();
00351 }
00352
00354 template <class T>
00355 inline T* COWReferenceClone(T* obj)
00356 {
00357
00358
00359 return obj->clone();
00360 }
00361
00362 }
00363
00364 #endif // BLOCXX_COWREFERENCE_HPP_