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 
00034 
00035 
00036 
00037 
00038 
00039 
00045 #ifndef OW_COW_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00046 #define OW_COW_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00047 
00048 #include "OW_config.h"
00049 
00050 namespace OW_NAMESPACE
00051 {
00052 
00053 #ifdef OW_CHECK_NULL_REFERENCES
00054 namespace COWIntrusiveReferenceHelpers
00055 {
00056    
00057    OW_COMMON_API void throwNULLException();
00058    inline void checkNull(const void* p)
00059    {
00060       if (p == 0)
00061       {
00062          throwNULLException();
00063       }
00064    }
00065 }
00066 #endif
00067 
00090 template<class T> class COWIntrusiveReference
00091 {
00092 private:
00093    typedef COWIntrusiveReference this_type;
00094 public:
00095    typedef T element_type;
00096 
00097    COWIntrusiveReference(): m_pObj(0)
00098    {
00099    }
00100    COWIntrusiveReference(T * p, bool addRef = true): m_pObj(p)
00101    {
00102       if (m_pObj != 0 && addRef) COWIntrusiveReferenceAddRef(m_pObj);
00103    }
00104    template<class U> COWIntrusiveReference(COWIntrusiveReference<U> const & rhs): m_pObj(rhs.m_pObj)
00105    {
00106       if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj);
00107    }
00108    COWIntrusiveReference(COWIntrusiveReference const & rhs): m_pObj(rhs.m_pObj)
00109    {
00110       if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj);
00111    }
00112    ~COWIntrusiveReference()
00113    {
00114       if (m_pObj != 0) COWIntrusiveReferenceRelease(m_pObj);
00115    }
00116    template<class U> COWIntrusiveReference & operator=(COWIntrusiveReference<U> const & rhs)
00117    {
00118       this_type(rhs).swap(*this);
00119       return *this;
00120    }
00121    COWIntrusiveReference & operator=(COWIntrusiveReference const & rhs)
00122    {
00123       this_type(rhs).swap(*this);
00124       return *this;
00125    }
00126    COWIntrusiveReference & operator=(T * rhs)
00127    {
00128       this_type(rhs).swap(*this);
00129       return *this;
00130    }
00131    const T * getPtr() const
00132    {
00133       return m_pObj;
00134    }
00135    
00136    const T & operator*() const
00137    {
00138 #ifdef OW_CHECK_NULL_REFERENCES
00139       COWIntrusiveReferenceHelpers::checkNull(this);
00140       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00141 #endif
00142       return *m_pObj;
00143    }
00144    
00145    const T * operator->() const
00146    {
00147 #ifdef OW_CHECK_NULL_REFERENCES
00148       COWIntrusiveReferenceHelpers::checkNull(this);
00149       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00150 #endif
00151       return m_pObj;
00152    }
00153 
00154    T & operator*()
00155    {
00156 #ifdef OW_CHECK_NULL_REFERENCES
00157       COWIntrusiveReferenceHelpers::checkNull(this);
00158       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00159 #endif
00160       getWriteLock();
00161       return *m_pObj;
00162    }
00163    
00164    T * operator->()
00165    {
00166 #ifdef OW_CHECK_NULL_REFERENCES
00167       COWIntrusiveReferenceHelpers::checkNull(this);
00168       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00169 #endif
00170       getWriteLock();
00171       return m_pObj;
00172    }
00173 
00174    typedef T * this_type::*unspecified_bool_type;
00175    operator unspecified_bool_type () const
00176    {
00177       return m_pObj == 0? 0: &this_type::m_pObj;
00178    }
00179 
00180    bool operator! () const
00181    {
00182       return m_pObj == 0;
00183    }
00184    
00185    void swap(COWIntrusiveReference & rhs)
00186    {
00187       T * tmp = m_pObj;
00188       m_pObj = rhs.m_pObj;
00189       rhs.m_pObj = tmp;
00190    }
00191 
00192 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00193    
00194    template <class U> friend class COWIntrusiveReference;
00195 private:
00196 #endif
00197 
00198    void getWriteLock()
00199    {
00200       if ((m_pObj != 0) && !COWIntrusiveReferenceUnique(m_pObj))
00201       {
00202          m_pObj = COWIntrusiveReferenceClone(m_pObj);
00203       }
00204    }
00205 
00206 
00207    T * m_pObj;
00208 };
00209 template<class T, class U> inline bool operator==(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b)
00210 {
00211    return a.getPtr() == b.getPtr();
00212 }
00213 template<class T, class U> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b)
00214 {
00215    return a.getPtr() != b.getPtr();
00216 }
00217 template<class T> inline bool operator==(COWIntrusiveReference<T> const & a, const T * b)
00218 {
00219    return a.getPtr() == b;
00220 }
00221 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, const T * b)
00222 {
00223    return a.getPtr() != b;
00224 }
00225 template<class T> inline bool operator==(const T * a, COWIntrusiveReference<T> const & b)
00226 {
00227    return a == b.getPtr();
00228 }
00229 template<class T> inline bool operator!=(const T * a, COWIntrusiveReference<T> const & b)
00230 {
00231    return a != b.getPtr();
00232 }
00233 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
00234 
00235 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b)
00236 {
00237    return a.getPtr() != b.getPtr();
00238 }
00239 #endif
00240 template<class T> inline bool operator<(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b)
00241 {
00242    return a.getPtr() < b.getPtr();
00243 }
00244 template<class T> void swap(COWIntrusiveReference<T> & lhs, COWIntrusiveReference<T> & rhs)
00245 {
00246    lhs.swap(rhs);
00247 }
00248 
00249 } 
00250 
00251 #endif
00252