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
00035 #ifndef OWBI1_COWREFERENCE_HPP_INCLUDE_GUARD_
00036 #define OWBI1_COWREFERENCE_HPP_INCLUDE_GUARD_
00037 #include "OWBI1_config.h"
00038 #include "OWBI1_COWReferenceBase.hpp"
00039
00040 namespace OWBI1
00041 {
00042
00044 template<class T>
00045 class COWReference : private COWReferenceBase
00046 {
00047 public:
00048 typedef T element_type;
00049
00050 COWReference();
00051 explicit COWReference(T* ptr);
00052 COWReference(const COWReference<T>& arg);
00053
00054
00055
00056 template <class U>
00057 COWReference(const COWReference<U>& arg);
00058 ~COWReference();
00059 COWReference<T>& operator= (const COWReference<T>& arg);
00060 COWReference<T>& operator= (T* newObj);
00061 void swap(COWReference<T>& arg);
00062 T* operator->();
00063 T& operator*();
00064 const T* operator->() const;
00065 const T& operator*() const;
00066 const T* getPtr() const;
00067
00068 typedef T* volatile COWReference::*safe_bool;
00069 operator safe_bool () const
00070 { return m_pObj ? &COWReference::m_pObj : 0; }
00071 bool operator!() const
00072 { return !m_pObj; }
00073
00074 template <class U>
00075 COWReference<U> cast_to() const;
00076
00077 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00078
00079 template <class U> friend class COWReference;
00080 private:
00081 #endif
00082 T* volatile m_pObj;
00083 void decRef();
00084 void getWriteLock();
00085 };
00087 template<class T>
00088 inline COWReference<T>::COWReference()
00089 : COWReferenceBase(), m_pObj(0)
00090 {
00091 }
00093 template<class T>
00094 inline COWReference<T>::COWReference(T* ptr)
00095 : COWReferenceBase(), m_pObj(ptr)
00096 {
00097 }
00099 template<class T>
00100 inline COWReference<T>::COWReference(const COWReference<T>& arg)
00101 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00102 {
00103 }
00105 template<class T>
00106 template<class U>
00107 inline COWReference<T>::COWReference(const COWReference<U>& arg)
00108 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00109 {
00110 }
00112 template<class T>
00113 inline COWReference<T>::~COWReference()
00114 {
00115 try
00116 {
00117 decRef();
00118 }
00119 catch (...)
00120 {
00121
00122 }
00123 }
00125 template<class T>
00126 inline void COWReference<T>::decRef()
00127 {
00128 typedef char type_must_be_complete[sizeof(T)];
00129 if (COWReferenceBase::decRef())
00130 {
00131 delete m_pObj;
00132 m_pObj = 0;
00133 }
00134 }
00135
00137 template<class T>
00138 inline void COWReference<T>::getWriteLock()
00139 {
00140 if (COWReferenceBase::refCountGreaterThanOne())
00141 {
00142
00143
00144 T* tmp = OWBI1::COWReferenceClone(m_pObj);
00145
00146 if (COWReferenceBase::getWriteLock())
00147 {
00148 delete tmp;
00149 }
00150 else
00151 {
00152 m_pObj = tmp;
00153 }
00154 }
00155 }
00157 template<class T>
00158 inline COWReference<T>& COWReference<T>::operator= (const COWReference<T>& arg)
00159 {
00160 COWReference<T>(arg).swap(*this);
00161 return *this;
00162 }
00164 template<class T>
00165 inline COWReference<T>& COWReference<T>::operator= (T* newObj)
00166 {
00167 COWReference<T>(newObj).swap(*this);
00168 return *this;
00169 }
00171 template <class T>
00172 inline void COWReference<T>::swap(COWReference<T>& arg)
00173 {
00174 COWReferenceBase::swap(arg);
00175 OWBI1::COWRefSwap(m_pObj, arg.m_pObj);
00176 }
00178 template<class T>
00179 inline T* COWReference<T>::operator->()
00180 {
00181 #ifdef OWBI1_CHECK_NULL_REFERENCES
00182 checkNull(this);
00183 checkNull(m_pObj);
00184 #endif
00185 getWriteLock();
00186
00187 return m_pObj;
00188 }
00190 template<class T>
00191 inline T& COWReference<T>::operator*()
00192 {
00193 #ifdef OWBI1_CHECK_NULL_REFERENCES
00194 checkNull(this);
00195 checkNull(m_pObj);
00196 #endif
00197 getWriteLock();
00198
00199 return *(m_pObj);
00200 }
00202 template<class T>
00203 inline const T* COWReference<T>::operator->() const
00204 {
00205 #ifdef OWBI1_CHECK_NULL_REFERENCES
00206 checkNull(this);
00207 checkNull(m_pObj);
00208 #endif
00209
00210 return m_pObj;
00211 }
00213 template<class T>
00214 inline const T& COWReference<T>::operator*() const
00215 {
00216 #ifdef OWBI1_CHECK_NULL_REFERENCES
00217 checkNull(this);
00218 checkNull(m_pObj);
00219 #endif
00220
00221 return *(m_pObj);
00222 }
00224 template<class T>
00225 inline const T* COWReference<T>::getPtr() const
00226 {
00227 return m_pObj;
00228 }
00230 template <class T>
00231 template <class U>
00232 inline COWReference<U>
00233 COWReference<T>::cast_to() const
00234 {
00235 COWReference<U> rval;
00236 rval.m_pObj = dynamic_cast<U*>(m_pObj);
00237 if (rval.m_pObj)
00238 {
00239 rval.useRefCountOf(*this);
00240 rval.incRef();
00241 }
00242 return rval;
00243 }
00245
00246 template <class T, class U>
00247 inline bool operator==(const COWReference<T>& a, const COWReference<U>& b)
00248 {
00249 return a.getPtr() == b.getPtr();
00250 }
00252 template <class T, class U>
00253 inline bool operator!=(const COWReference<T>& a, const COWReference<U>& b)
00254 {
00255 return a.getPtr() != b.getPtr();
00256 }
00258 template <class T, class U>
00259 inline bool operator<(const COWReference<T>& a, const COWReference<U>& b)
00260 {
00261 return a.getPtr() < b.getPtr();
00262 }
00263
00265 template <class T>
00266 inline T* COWReferenceClone(T* obj)
00267 {
00268
00269
00270 return obj->clone();
00271 }
00272
00273 }
00274
00275 #endif // OWBI1_COWREFERENCE_HPP_