blocxx

IntrusiveReference.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2006, 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 *     * Redistributions in binary form must reproduce the above copyright
00011 *       notice, this list of conditions and the following disclaimer in the
00012 *       documentation and/or other materials provided with the distribution.
00013 *     * Neither the name of 
00014 *       Vintela, Inc., 
00015 *       nor Novell, Inc., 
00016 *       nor the names of its contributors or employees may be used to 
00017 *       endorse or promote products derived from this software without 
00018 *       specific prior written permission.
00019 * 
00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030 * POSSIBILITY OF SUCH DAMAGE.
00031 *******************************************************************************/
00032 
00033 
00034 //
00035 //  Copyright (c) 2001, 2002 Peter Dimov
00036 //
00037 //  Permission to copy, use, modify, sell and distribute this software
00038 //  is granted provided this copyright notice appears in all copies.
00039 //  This software is provided "as is" without express or implied
00040 //  warranty, and with no claim as to its suitability for any purpose.
00041 //
00042 
00049 #ifndef BLOCXX_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00050 #define BLOCXX_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00051 
00052 #include "blocxx/BLOCXX_config.h"
00053 #include "blocxx/ReferenceHelpers.hpp"
00054 #include "blocxx/SafeBool.hpp"
00055 
00056 namespace BLOCXX_NAMESPACE
00057 {
00058 
00059 //
00060 //  IntrusiveReference
00061 //
00062 //  A smart pointer that uses intrusive reference counting.
00063 //
00064 //  Relies on unqualified calls to
00065 //  
00066 //      void IntrusiveReferenceAddRef(T * p);
00067 //      void IntrusiveReferenceRelease(T * p);
00068 //
00069 //          (p != 0)
00070 //
00071 //  The object is responsible for destroying itself.
00072 //
00073 
00074 
00075 template<class T> class IntrusiveReference
00076 {
00077 private:
00078    typedef IntrusiveReference this_type;
00079 public:
00080    typedef T element_type;
00081 
00082    IntrusiveReference(): m_pObj(0)
00083    {
00084    }
00085    IntrusiveReference(T * p, bool add_ref = true): m_pObj(p)
00086    {
00087       if (m_pObj != 0 && add_ref) IntrusiveReferenceAddRef(m_pObj);
00088    }
00089    template<class U> IntrusiveReference(IntrusiveReference<U> const & rhs): m_pObj(rhs.getPtr())
00090    {
00091       if (m_pObj != 0) IntrusiveReferenceAddRef(m_pObj);
00092    }
00093    IntrusiveReference(IntrusiveReference const & rhs): m_pObj(rhs.m_pObj)
00094    {
00095       if (m_pObj != 0) IntrusiveReferenceAddRef(m_pObj);
00096    }
00097    ~IntrusiveReference()
00098    {
00099       if (m_pObj != 0) IntrusiveReferenceRelease(m_pObj);
00100    }
00101    template<class U> IntrusiveReference & operator=(IntrusiveReference<U> const & rhs)
00102    {
00103       this_type(rhs).swap(*this);
00104       return *this;
00105    }
00106    IntrusiveReference & operator=(IntrusiveReference const & rhs)
00107    {
00108       this_type(rhs).swap(*this);
00109       return *this;
00110    }
00111    IntrusiveReference & operator=(T * rhs)
00112    {
00113       this_type(rhs).swap(*this);
00114       return *this;
00115    }
00116    T * getPtr() const
00117    {
00118       return m_pObj;
00119    }
00120    T & operator*() const
00121    {
00122 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00123       ReferenceHelpers::checkNull(this);
00124       ReferenceHelpers::checkNull(m_pObj);
00125 #endif
00126       return *m_pObj;
00127    }
00128    T * operator->() const
00129    {
00130 #ifdef BLOCXX_CHECK_NULL_REFERENCES
00131       ReferenceHelpers::checkNull(this);
00132       ReferenceHelpers::checkNull(m_pObj);
00133 #endif
00134       return m_pObj;
00135    }
00136 
00137    BLOCXX_SAFE_BOOL_IMPL(this_type, T*, this_type::m_pObj, m_pObj)
00138 
00139    BLOCXX_DEPRECATED bool isNull() const // in 3.1.0
00140    {
00141        return m_pObj == 0;
00142    }
00143 
00144    void swap(IntrusiveReference & rhs)
00145    {
00146       T * tmp = m_pObj;
00147       m_pObj = rhs.m_pObj;
00148       rhs.m_pObj = tmp;
00149    }
00150 
00151    template <class U>
00152    IntrusiveReference<U> cast_to() const
00153    {
00154       return IntrusiveReference<U>(dynamic_cast<U*>(m_pObj));
00155    }
00156 
00157 private:
00158    T * m_pObj;
00159 };
00160 template<class T, class U> inline bool operator==(IntrusiveReference<T> const & a, IntrusiveReference<U> const & b)
00161 {
00162    return a.getPtr() == b.getPtr();
00163 }
00164 template<class T, class U> inline bool operator!=(IntrusiveReference<T> const & a, IntrusiveReference<U> const & b)
00165 {
00166    return a.getPtr() != b.getPtr();
00167 }
00168 template<class T> inline bool operator==(IntrusiveReference<T> const & a, T * b)
00169 {
00170    return a.getPtr() == b;
00171 }
00172 template<class T> inline bool operator!=(IntrusiveReference<T> const & a, T * b)
00173 {
00174    return a.getPtr() != b;
00175 }
00176 template<class T> inline bool operator==(T * a, IntrusiveReference<T> const & b)
00177 {
00178    return a == b.getPtr();
00179 }
00180 template<class T> inline bool operator!=(T * a, IntrusiveReference<T> const & b)
00181 {
00182    return a != b.getPtr();
00183 }
00184 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
00185 // Resolve the ambiguity between our op!= and the one in rel_ops
00186 template<class T> inline bool operator!=(IntrusiveReference<T> const & a, IntrusiveReference<T> const & b)
00187 {
00188    return a.getPtr() != b.getPtr();
00189 }
00190 #endif
00191 template<class T> inline bool operator<(IntrusiveReference<T> const & a, IntrusiveReference<T> const & b)
00192 {
00193    return a.getPtr() < b.getPtr();
00194 }
00195 template<class T> void swap(IntrusiveReference<T> & lhs, IntrusiveReference<T> & rhs)
00196 {
00197    lhs.swap(rhs);
00198 }
00199 template<class T, class U> IntrusiveReference<T> static_pointer_cast(IntrusiveReference<U> const & p)
00200 {
00201    return static_cast<T *>(p.getPtr());
00202 }
00203 template<class T, class U> IntrusiveReference<T> const_pointer_cast(IntrusiveReference<U> const & p)
00204 {
00205    return const_cast<T *>(p.getPtr());
00206 }
00207 template<class T, class U> IntrusiveReference<T> dynamic_pointer_cast(IntrusiveReference<U> const & p)
00208 {
00209    return dynamic_cast<T *>(p.getPtr());
00210 }
00211 
00212 } // end namespace BLOCXX_NAMESPACE
00213 
00214 #endif