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

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 
00087 template<class T> class COWIntrusiveReference
00088 {
00089 private:
00090    typedef COWIntrusiveReference this_type;
00091 public:
00092    typedef T element_type;
00093 
00098    COWIntrusiveReference(): m_pObj(0)
00099    {
00100    }
00108    COWIntrusiveReference(T * p, bool addRef = true): m_pObj(p)
00109    {
00110       if (m_pObj != 0 && addRef) COWIntrusiveReferenceAddRef(m_pObj);
00111    }
00122    template<class U> COWIntrusiveReference(COWIntrusiveReference<U> const & rhs): m_pObj(rhs.m_pObj)
00123    {
00124       if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj);
00125    }
00134    COWIntrusiveReference(COWIntrusiveReference const & rhs): m_pObj(rhs.m_pObj)
00135    {
00136       if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj);
00137    }
00143    ~COWIntrusiveReference()
00144    {
00145       if (m_pObj != 0) COWIntrusiveReferenceRelease(m_pObj);
00146    }
00147 
00159    template<class U> COWIntrusiveReference & operator=(COWIntrusiveReference<U> const & rhs)
00160    {
00161       this_type(rhs).swap(*this);
00162       return *this;
00163    }
00174    COWIntrusiveReference & operator=(COWIntrusiveReference const & rhs)
00175    {
00176       this_type(rhs).swap(*this);
00177       return *this;
00178    }
00187    COWIntrusiveReference & operator=(T * rhs)
00188    {
00189       this_type(rhs).swap(*this);
00190       return *this;
00191    }
00196    const T * getPtr() const
00197    {
00198       return m_pObj;
00199    }
00200 
00205    const T & operator*() const
00206    {
00207 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00208       COWIntrusiveReferenceHelpers::checkNull(this);
00209       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00210 #endif
00211       return *m_pObj;
00212    }
00213    
00218    const T * operator->() const
00219    {
00220 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00221       COWIntrusiveReferenceHelpers::checkNull(this);
00222       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00223 #endif
00224       return m_pObj;
00225    }
00226 
00231    T & operator*()
00232    {
00233 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00234       COWIntrusiveReferenceHelpers::checkNull(this);
00235       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00236 #endif
00237       getWriteLock();
00238       return *m_pObj;
00239    }
00240    
00245    T * operator->()
00246    {
00247 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00248       COWIntrusiveReferenceHelpers::checkNull(this);
00249       COWIntrusiveReferenceHelpers::checkNull(m_pObj);
00250 #endif
00251       getWriteLock();
00252       return m_pObj;
00253    }
00254 
00255    typedef T * this_type::*unspecified_bool_type;
00256    operator unspecified_bool_type () const
00257    {
00258       return m_pObj == 0? 0: &this_type::m_pObj;
00259    }
00260 
00266    bool operator! () const
00267    {
00268       return m_pObj == 0;
00269    }
00270 
00271    void swap(COWIntrusiveReference & rhs)
00272    {
00273       T * tmp = m_pObj;
00274       m_pObj = rhs.m_pObj;
00275       rhs.m_pObj = tmp;
00276    }
00277 
00278 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
00279    /* This is so the templated constructor will work */
00280    template <class U> friend class COWIntrusiveReference;
00281 private:
00282 #endif
00283 
00289    void getWriteLock()
00290    {
00291       if ((m_pObj != 0) && !COWIntrusiveReferenceUnique(m_pObj))
00292       {
00293          m_pObj = COWIntrusiveReferenceClone(m_pObj);
00294       }
00295    }
00296 
00297 
00298    T * m_pObj;
00299 };
00300 template<class T, class U> inline bool operator==(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b)
00301 {
00302    return a.getPtr() == b.getPtr();
00303 }
00304 template<class T, class U> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b)
00305 {
00306    return a.getPtr() != b.getPtr();
00307 }
00308 template<class T> inline bool operator==(COWIntrusiveReference<T> const & a, const T * b)
00309 {
00310    return a.getPtr() == b;
00311 }
00312 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, const T * b)
00313 {
00314    return a.getPtr() != b;
00315 }
00316 template<class T> inline bool operator==(const T * a, COWIntrusiveReference<T> const & b)
00317 {
00318    return a == b.getPtr();
00319 }
00320 template<class T> inline bool operator!=(const T * a, COWIntrusiveReference<T> const & b)
00321 {
00322    return a != b.getPtr();
00323 }
00324 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
00325 // Resolve the ambiguity between our op!= and the one in rel_ops
00326 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b)
00327 {
00328    return a.getPtr() != b.getPtr();
00329 }
00330 #endif
00331 template<class T> inline bool operator<(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b)
00332 {
00333    return a.getPtr() < b.getPtr();
00334 }
00335 template<class T> void swap(COWIntrusiveReference<T> & lhs, COWIntrusiveReference<T> & rhs)
00336 {
00337    lhs.swap(rhs);
00338 }
00339 
00340 } // end namespace BLOCXX_NAMESPACE
00341 
00342 #endif
00343 

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