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_