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_