OW_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 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       /* 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       bool isNull() const OW_DEPRECATED; // in 3.1.0
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       /* This is so the templated constructor will work */
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       // don't let exceptions escape
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       // this needs to happen first to avoid a race condition between 
00147       // another thread deleting the object and this one making a copy.
00148       T* tmp = COWReferenceClone(m_pObj);
00149       // this will decrement the count and then make a new one if we're making a copy.
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 // Comparisons
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    // default implementation.  If a certain class doesn't have clone()
00286    // (like std::vector), then they can overload this function
00287    return obj->clone();
00288 }
00289 
00290 } // end namespace OW_NAMESPACE
00291 
00292 #endif   // OW_COWREFERENCE_HPP_

Generated on Thu Feb 9 08:47:57 2006 for openwbem by  doxygen 1.4.6