OWBI1_COWReference.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are met:
00006  *
00007  *  - Redistributions of source code must retain the above copyright notice,
00008  *    this list of conditions and the following disclaimer.
00009  *
00010  *  - Redistributions in binary form must reproduce the above copyright notice,
00011  *    this list of conditions and the following disclaimer in the documentation
00012  *    and/or other materials provided with the distribution.
00013  *
00014  *  - Neither the name of Vintela, Inc. nor the names of its
00015  *    contributors may be used to endorse or promote products derived from this
00016  *    software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
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       /* construct out of a reference to a derived type.  U should be
00055       derived from T */
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       /* This is so the templated constructor will work */
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       // don't let exceptions escape
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       // this needs to happen first to avoid a race condition between 
00143       // another thread deleting the object and this one making a copy.
00144       T* tmp = OWBI1::COWReferenceClone(m_pObj);
00145       // this will decrement the count and then make a new one if we're making a copy.
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 // Comparisons
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    // default implementation.  If a certain class doesn't have clone()
00269    // (like std::vector), then they can overload this function
00270    return obj->clone();
00271 }
00272 
00273 } // end namespace OWBI1
00274 
00275 #endif   // OWBI1_COWREFERENCE_HPP_

Generated on Thu Feb 9 08:48:27 2006 for openwbem by  doxygen 1.4.6