Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

COWReference.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * Copyright (C) 2004 Vintela, Inc. All rights reserved.
00003  * Copyright (C) 2005 Novell, Inc. All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *  - Redistributions of source code must retain the above copyright notice,
00009  *    this list of conditions and the following disclaimer.
00010  *
00011  *  - Redistributions in binary form must reproduce the above copyright notice,
00012  *    this list of conditions and the following disclaimer in the documentation
00013  *    and/or other materials provided with the distribution.
00014  *
00015  *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016  *    contributors may be used to endorse or promote products derived from this
00017  *    software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE 
00023  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  *******************************************************************************/
00031 
00032 
00037 #ifndef BLOCXX_COWREFERENCE_HPP_INCLUDE_GUARD_
00038 #define BLOCXX_COWREFERENCE_HPP_INCLUDE_GUARD_
00039 #include "blocxx/BLOCXX_config.h"
00040 #include "blocxx/COWReferenceBase.hpp"
00041 
00042 namespace BLOCXX_NAMESPACE
00043 {
00044 
00050 template<class T>
00051 class COWReference : private COWReferenceBase
00052 {
00053 public:
00054    typedef T element_type;
00055 
00060    COWReference();
00061 
00066    explicit COWReference(T* ptr);
00067 
00074    COWReference(const COWReference<T>& arg);
00075 
00083    template <class U>
00084    COWReference(const COWReference<U>& arg);
00085 
00091    ~COWReference();
00092 
00101    COWReference<T>& operator= (const COWReference<T>& arg);
00102 
00112    COWReference<T>& operator= (T* newObj);
00113 
00114    void swap(COWReference<T>& arg);
00115 
00119    T* operator->();
00120    
00124    const T* operator->() const;
00125 
00129    T& operator*();
00130 
00134    const T& operator*() const;
00135 
00139    const T* getPtr() const;
00140 
00141    typedef T* volatile COWReference::*safe_bool;
00142    operator safe_bool () const
00143    {  
00144       return m_pObj ? &COWReference::m_pObj : 0; 
00145    }
00146 
00152    bool operator!() const
00153    {  
00154       return !m_pObj; 
00155    }
00156 
00157    template <class U>
00158       COWReference<U> cast_to() const;
00159 
00160 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00161    /* This is so the templated constructor will work */
00162    template <class U> friend class COWReference;
00163 private:
00164 #endif
00165    T* volatile m_pObj;
00166    void decRef();
00167    void getWriteLock();
00168 };
00169 
00171 template<class T>
00172 inline COWReference<T>::COWReference()
00173 : COWReferenceBase(), m_pObj(0)
00174 {
00175 }
00177 template<class T>
00178 inline COWReference<T>::COWReference(T* ptr)
00179 : COWReferenceBase(), m_pObj(ptr)
00180 {
00181 }
00183 template<class T>
00184 inline COWReference<T>::COWReference(const COWReference<T>& arg)
00185 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00186 {
00187 }
00189 template<class T>
00190 template<class U>
00191 inline COWReference<T>::COWReference(const COWReference<U>& arg)
00192 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
00193 {
00194 }
00196 template<class T>
00197 inline COWReference<T>::~COWReference()
00198 {
00199    try
00200    {
00201       decRef();
00202    }
00203    catch (...)
00204    {
00205       // don't let exceptions escape
00206    }
00207 }
00209 template<class T>
00210 inline void COWReference<T>::decRef()
00211 {
00212    typedef char type_must_be_complete[sizeof(T)];
00213    if (COWReferenceBase::decRef())
00214    {
00215       delete m_pObj;
00216       m_pObj = 0;
00217    }
00218 }
00219 
00221 template<class T>
00222 inline void COWReference<T>::getWriteLock()
00223 {
00224    if (COWReferenceBase::refCountGreaterThanOne())
00225    {
00226       // this needs to happen first to avoid a race condition between 
00227       // another thread deleting the object and this one making a copy.
00228       T* tmp = COWReferenceClone(m_pObj);
00229       // this will decrement the count and then make a new one if we're making a copy.
00230       if (COWReferenceBase::getWriteLock())
00231       {
00232          delete tmp;
00233       }
00234       else
00235       {
00236          m_pObj = tmp;
00237       }
00238    }
00239 }
00241 template<class T>
00242 inline COWReference<T>& COWReference<T>::operator= (const COWReference<T>& arg)
00243 {
00244    COWReference<T>(arg).swap(*this);
00245    return *this;
00246 }
00248 template<class T>
00249 inline COWReference<T>& COWReference<T>::operator= (T* newObj)
00250 {
00251    COWReference<T>(newObj).swap(*this);
00252    return *this;
00253 }
00255 template <class T>
00256 inline void COWReference<T>::swap(COWReference<T>& arg)
00257 {
00258    COWReferenceBase::swap(arg);
00259    COWRefSwap(m_pObj, arg.m_pObj);
00260 }
00262 template<class T>
00263 inline T* COWReference<T>::operator->()
00264 {
00265 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00266    checkNull(this);
00267    checkNull(m_pObj);
00268 #endif
00269    getWriteLock();
00270 
00271    return m_pObj;
00272 }
00274 template<class T>
00275 inline T& COWReference<T>::operator*()
00276 {
00277 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00278    checkNull(this);
00279    checkNull(m_pObj);
00280 #endif
00281    getWriteLock();
00282 
00283    return *(m_pObj);
00284 }
00286 template<class T>
00287 inline const T* COWReference<T>::operator->() const
00288 {
00289 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00290    checkNull(this);
00291    checkNull(m_pObj);
00292 #endif
00293 
00294    return m_pObj;
00295 }
00297 template<class T>
00298 inline const T& COWReference<T>::operator*() const
00299 {
00300 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00301    checkNull(this);
00302    checkNull(m_pObj);
00303 #endif
00304 
00305    return *(m_pObj);
00306 }
00308 template<class T>
00309 inline const T* COWReference<T>::getPtr() const
00310 {
00311    return m_pObj;
00312 }
00314 template <class T>
00315 template <class U>
00316 inline COWReference<U>
00317 COWReference<T>::cast_to() const
00318 {
00319    COWReference<U> rval;
00320    rval.m_pObj = dynamic_cast<U*>(m_pObj);
00321    if (rval.m_pObj)
00322    {
00323       rval.useRefCountOf(*this);
00324       rval.incRef();
00325    }
00326    return rval;
00327 }
00329 // Comparisons
00330 template <class T, class U>
00331 inline bool operator==(const COWReference<T>& a, const COWReference<U>& b)
00332 {
00333    return a.getPtr() == b.getPtr();
00334 }
00336 template <class T, class U>
00337 inline bool operator!=(const COWReference<T>& a, const COWReference<U>& b)
00338 {
00339    return a.getPtr() != b.getPtr();
00340 }
00342 template <class T, class U>
00343 inline bool operator<(const COWReference<T>& a, const COWReference<U>& b)
00344 {
00345    return a.getPtr() < b.getPtr();
00346 }
00347 
00349 template <class T>
00350 inline T* COWReferenceClone(T* obj)
00351 {
00352    // default implementation.  If a certain class doesn't have clone()
00353    // (like std::vector), then they can overload this function
00354    return obj->clone();
00355 }
00356 
00357 } // end namespace BLOCXX_NAMESPACE
00358 
00359 #endif   // BLOCXX_COWREFERENCE_HPP_

Generated on Mon Sep 12 23:56:34 2005 for blocxx by  doxygen 1.4.4