COWIntrusiveReference.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 
00033 //
00034 //  Copyright (c) 2001, 2002 Peter Dimov
00035 //
00036 //  Permission to copy, use, modify, sell and distribute this software
00037 //  is granted provided this copyright notice appears in all copies.
00038 //  This software is provided "as is" without express or implied
00039 //  warranty, and with no claim as to its suitability for any purpose.
00040 //
00041 
00047 #ifndef BLOCXX_COW_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00048 #define BLOCXX_COW_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00049 
00050 #include "blocxx/BLOCXX_config.h"
00051 
00052 namespace BLOCXX_NAMESPACE
00053 {
00054 
00055 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00056 namespace COWIntrusiveReferenceHelpers
00057 {
00058    // these are not part of COWIntrusiveReference to try and avoid template bloat.
00059    BLOCXX_COMMON_API void throwNULLException();
00060    inline void checkNull(const void* p)
00061    {
00062       if (p == 0)
00063       {
00064          throwNULLException();
00065       }
00066    }
00067 }
00068 #endif
00069 
00088 template<class T> class COWIntrusiveReference
00089 {
00090 private:
00091    typedef COWIntrusiveReference this_type;
00092 public:
00093    typedef T element_type;
00094 
00099    COWIntrusiveReference(): m_pObj(0)
00100    {
00101    }
00109    COWIntrusiveReference(T * p, bool addRef = true): m_pObj(p)
00110    {
00111       if (m_pObj != 0 && addRef) COWIntrusiveReferenceAddRef(m_pObj);
00112    }
00123    template<class U> COWIntrusiveReference(COWIntrusiveReference<U> const & rhs): m_pObj(rhs.m_pObj)
00124    {
00125       if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj);
00126    }
00135    COWIntrusiveReference(COWIntrusiveReference const & rhs): m_pObj(rhs.m_pObj)
00136    {
00137       if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj);
00138    }
00144    ~COWIntrusiveReference()
00145    {
00146       if (m_pObj != 0) COWIntrusiveReferenceRelease(m_pObj);
00147    }
00148 
00160    template<class U> COWIntrusiveReference & operator=(COWIntrusiveReference<U> const & rhs)
00161    {
00162       this_type(rhs).swap(*this);
00163       return *this;
00164    }
00175    COWIntrusiveReference & operator=(COWIntrusiveReference const & rhs)
00176    {
00177       this_type(rhs).swap(*this);
00178       return *this;
00179    }
00188    COWIntrusiveReference & operator=(T * rhs)
00189    {
00190       this_type(rhs).swap(*this);
00191       return *this;
00192    }
00197    const T * getPtr() const
00198    {
00199       return m_pObj;
00200    }
00201 
00206    const T & operator*() const
00207    {
00208 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00209       COWIntrusiveReferenceHelpers::checkNull(this);
00210       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00211 #endif
00212       return *m_pObj;
00213    }
00214    
00219    const T * operator->() const
00220    {
00221 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00222       COWIntrusiveReferenceHelpers::checkNull(this);
00223       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00224 #endif
00225       return m_pObj;
00226    }
00227 
00232    T & operator*()
00233    {
00234 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00235       COWIntrusiveReferenceHelpers::checkNull(this);
00236       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00237 #endif
00238       getWriteLock();
00239       return *m_pObj;
00240    }
00241    
00246    T * operator->()
00247    {
00248 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00249       COWIntrusiveReferenceHelpers::checkNull(this);
00250       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00251 #endif
00252       getWriteLock();
00253       return m_pObj;
00254    }
00255 
00256    typedef T * this_type::*unspecified_bool_type;
00257    operator unspecified_bool_type () const
00258    {
00259       return m_pObj == 0? 0: &this_type::m_pObj;
00260    }
00261 
00267    bool operator! () const
00268    {
00269       return m_pObj == 0;
00270    }
00271 
00272    void swap(COWIntrusiveReference & rhs)
00273    {
00274       T * tmp = m_pObj;
00275       m_pObj = rhs.m_pObj;
00276       rhs.m_pObj = tmp;
00277    }
00278 
00279 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00280    /* This is so the templated constructor will work */
00281    template <class U> friend class COWIntrusiveReference;
00282 private:
00283 #endif
00284 
00290    void getWriteLock()
00291    {
00292       if ((m_pObj != 0) && !COWIntrusiveReferenceUnique(m_pObj))
00293       {
00294          m_pObj = COWIntrusiveReferenceClone(m_pObj);
00295       }
00296    }
00297 
00298 
00299    T * m_pObj;
00300 };
00301 template<class T, class U> inline bool operator==(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b)
00302 {
00303    return a.getPtr() == b.getPtr();
00304 }
00305 template<class T, class U> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b)
00306 {
00307    return a.getPtr() != b.getPtr();
00308 }
00309 template<class T> inline bool operator==(COWIntrusiveReference<T> const & a, const T * b)
00310 {
00311    return a.getPtr() == b;
00312 }
00313 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, const T * b)
00314 {
00315    return a.getPtr() != b;
00316 }
00317 template<class T> inline bool operator==(const T * a, COWIntrusiveReference<T> const & b)
00318 {
00319    return a == b.getPtr();
00320 }
00321 template<class T> inline bool operator!=(const T * a, COWIntrusiveReference<T> const & b)
00322 {
00323    return a != b.getPtr();
00324 }
00325 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
00326 // Resolve the ambiguity between our op!= and the one in rel_ops
00327 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b)
00328 {
00329    return a.getPtr() != b.getPtr();
00330 }
00331 #endif
00332 template<class T> inline bool operator<(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b)
00333 {
00334    return a.getPtr() < b.getPtr();
00335 }
00336 template<class T> void swap(COWIntrusiveReference<T> & lhs, COWIntrusiveReference<T> & rhs)
00337 {
00338    lhs.swap(rhs);
00339 }
00340 
00341 } // end namespace BLOCXX_NAMESPACE
00342 
00343 #endif
00344 

Generated on Fri Jun 16 15:39:08 2006 for blocxx by  doxygen 1.4.6