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 OW_COWREFERENCE_HPP_INCLUDE_GUARD_
00036 #define OW_COWREFERENCE_HPP_INCLUDE_GUARD_
00037 #include "OW_config.h"
00038 #include "OW_COWReferenceBase.hpp"
00039
00040 namespace OW_NAMESPACE
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 bool isNull() const OW_DEPRECATED;
00068
00069 typedef T* volatile COWReference::*safe_bool;
00070 operator safe_bool () const
00071 { return m_pObj ? &COWReference::m_pObj : 0; }
00072 bool operator!() const
00073 { return !m_pObj; }
00074
00075 template <class U>
00076 COWReference<U> cast_to() const;
00077
00078 template <class U>
00079 void useRefCountOf(const COWReference<U>&);
00080
00081 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00082
00083 template <class U> friend class COWReference;
00084 private:
00085 #endif
00086 T* volatile m_pObj;
00087 void decRef();
00088 void getWriteLock();
00089 };
00091 template<class T>
00092 inline COWReference<T>::COWReference()
00093 : COWReferenceBase(), m_pObj(0)
00094 {
00095 }
00097 template<class T>
00098 inline COWReference<T>::COWReference(T* ptr)
00099 : COWReferenceBase(), m_pObj(ptr)
00100 {
00101 }
00103 template<class T>
00104 inline COWReference<T>::COWReference(const COWReference<T>& arg)
00105 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00106 {
00107 }
00109 template<class T>
00110 template<class U>
00111 inline COWReference<T>::COWReference(const COWReference<U>& arg)
00112 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00113 {
00114 }
00116 template<class T>
00117 inline COWReference<T>::~COWReference()
00118 {
00119 try
00120 {
00121 decRef();
00122 }
00123 catch (...)
00124 {
00125
00126 }
00127 }
00129 template<class T>
00130 inline void COWReference<T>::decRef()
00131 {
00132 typedef char type_must_be_complete[sizeof(T)];
00133 if (COWReferenceBase::decRef())
00134 {
00135 delete m_pObj;
00136 m_pObj = 0;
00137 }
00138 }
00139
00141 template<class T>
00142 inline void COWReference<T>::getWriteLock()
00143 {
00144 if (COWReferenceBase::refCountGreaterThanOne())
00145 {
00146
00147
00148 T* tmp = COWReferenceClone(m_pObj);
00149
00150 if (COWReferenceBase::getWriteLock())
00151 {
00152 delete tmp;
00153 }
00154 else
00155 {
00156 m_pObj = tmp;
00157 }
00158 }
00159 }
00161 template<class T>
00162 inline COWReference<T>& COWReference<T>::operator= (const COWReference<T>& arg)
00163 {
00164 COWReference<T>(arg).swap(*this);
00165 return *this;
00166 }
00168 template<class T>
00169 inline COWReference<T>& COWReference<T>::operator= (T* newObj)
00170 {
00171 COWReference<T>(newObj).swap(*this);
00172 return *this;
00173 }
00175 template <class T>
00176 inline void COWReference<T>::swap(COWReference<T>& arg)
00177 {
00178 COWReferenceBase::swap(arg);
00179 COWRefSwap(m_pObj, arg.m_pObj);
00180 }
00182 template<class T>
00183 inline T* COWReference<T>::operator->()
00184 {
00185 #ifdef OW_CHECK_NULL_REFERENCES
00186 checkNull(this);
00187 checkNull(m_pObj);
00188 #endif
00189 getWriteLock();
00190
00191 return m_pObj;
00192 }
00194 template<class T>
00195 inline T& COWReference<T>::operator*()
00196 {
00197 #ifdef OW_CHECK_NULL_REFERENCES
00198 checkNull(this);
00199 checkNull(m_pObj);
00200 #endif
00201 getWriteLock();
00202
00203 return *(m_pObj);
00204 }
00206 template<class T>
00207 inline const T* COWReference<T>::operator->() const
00208 {
00209 #ifdef OW_CHECK_NULL_REFERENCES
00210 checkNull(this);
00211 checkNull(m_pObj);
00212 #endif
00213
00214 return m_pObj;
00215 }
00217 template<class T>
00218 inline const T& COWReference<T>::operator*() const
00219 {
00220 #ifdef OW_CHECK_NULL_REFERENCES
00221 checkNull(this);
00222 checkNull(m_pObj);
00223 #endif
00224
00225 return *(m_pObj);
00226 }
00228 template<class T>
00229 inline const T* COWReference<T>::getPtr() const
00230 {
00231 return m_pObj;
00232 }
00234 template<class T>
00235 inline bool COWReference<T>::isNull() const
00236 {
00237 return (m_pObj == 0);
00238 }
00240 template <class T>
00241 template <class U>
00242 inline COWReference<U>
00243 COWReference<T>::cast_to() const
00244 {
00245 COWReference<U> rval;
00246 rval.m_pObj = dynamic_cast<U*>(m_pObj);
00247 if (rval.m_pObj)
00248 {
00249 rval.useRefCountOf(*this);
00250 }
00251 return rval;
00252 }
00254 template <class T>
00255 template <class U>
00256 inline void
00257 COWReference<T>::useRefCountOf(const COWReference<U>& arg)
00258 {
00259 COWReferenceBase::useRefCountOf(arg);
00260 }
00262
00263 template <class T, class U>
00264 inline bool operator==(const COWReference<T>& a, const COWReference<U>& b)
00265 {
00266 return a.getPtr() == b.getPtr();
00267 }
00269 template <class T, class U>
00270 inline bool operator!=(const COWReference<T>& a, const COWReference<U>& b)
00271 {
00272 return a.getPtr() != b.getPtr();
00273 }
00275 template <class T, class U>
00276 inline bool operator<(const COWReference<T>& a, const COWReference<U>& b)
00277 {
00278 return a.getPtr() < b.getPtr();
00279 }
00280
00282 template <class T>
00283 inline T* COWReferenceClone(T* obj)
00284 {
00285
00286
00287 return obj->clone();
00288 }
00289
00290 }
00291
00292 #endif // OW_COWREFERENCE_HPP_