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