IntrusiveReference.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 
00048 #ifndef BLOCXX_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00049 #define BLOCXX_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_
00050 
00051 #include "blocxx/BLOCXX_config.h"
00052 
00053 namespace BLOCXX_NAMESPACE
00054 {
00055 
00056 //
00057 //  IntrusiveReference
00058 //
00059 //  A smart pointer that uses intrusive reference counting.
00060 //
00061 //  Relies on unqualified calls to
00062 //  
00063 //      void IntrusiveReferenceAddRef(T * p);
00064 //      void IntrusiveReferenceRelease(T * p);
00065 //
00066 //          (p != 0)
00067 //
00068 //  The object is responsible for destroying itself.
00069 //
00070 
00071 
00072 template<class T> class IntrusiveReference
00073 {
00074 private:
00075    typedef IntrusiveReference this_type;
00076 public:
00077    typedef T element_type;
00078 
00079    IntrusiveReference(): m_pObj(0)
00080    {
00081    }
00082    IntrusiveReference(T * p, bool add_ref = true): m_pObj(p)
00083    {
00084       if (m_pObj != 0 && add_ref) IntrusiveReferenceAddRef(m_pObj);
00085    }
00086    template<class U> IntrusiveReference(IntrusiveReference<U> const & rhs): m_pObj(rhs.getPtr())
00087    {
00088       if (m_pObj != 0) IntrusiveReferenceAddRef(m_pObj);
00089    }
00090    IntrusiveReference(IntrusiveReference const & rhs): m_pObj(rhs.m_pObj)
00091    {
00092       if (m_pObj != 0) IntrusiveReferenceAddRef(m_pObj);
00093    }
00094    ~IntrusiveReference()
00095    {
00096       if (m_pObj != 0) IntrusiveReferenceRelease(m_pObj);
00097    }
00098    template<class U> IntrusiveReference & operator=(IntrusiveReference<U> const & rhs)
00099    {
00100       this_type(rhs).swap(*this);
00101       return *this;
00102    }
00103    IntrusiveReference & operator=(IntrusiveReference const & rhs)
00104    {
00105       this_type(rhs).swap(*this);
00106       return *this;
00107    }
00108    IntrusiveReference & operator=(T * rhs)
00109    {
00110       this_type(rhs).swap(*this);
00111       return *this;
00112    }
00113    T * getPtr() const
00114    {
00115       return m_pObj;
00116    }
00117    T & operator*() const
00118    {
00119       return *m_pObj;
00120    }
00121    T * operator->() const
00122    {
00123       return m_pObj;
00124    }
00125    typedef T * this_type::*safe_bool;
00126    operator safe_bool() const
00127    {
00128       return m_pObj == 0? 0: &this_type::m_pObj;
00129    }
00130    bool operator! () const
00131    {
00132       return m_pObj == 0;
00133    }
00134 
00135    void swap(IntrusiveReference & rhs)
00136    {
00137       T * tmp = m_pObj;
00138       m_pObj = rhs.m_pObj;
00139       rhs.m_pObj = tmp;
00140    }
00141 
00142    template <class U>
00143    IntrusiveReference<U> cast_to() const
00144    {
00145       return IntrusiveReference<U>(dynamic_cast<U*>(m_pObj));
00146    }
00147 
00148 private:
00149    T * m_pObj;
00150 };
00151 template<class T, class U> inline bool operator==(IntrusiveReference<T> const & a, IntrusiveReference<U> const & b)
00152 {
00153    return a.getPtr() == b.getPtr();
00154 }
00155 template<class T, class U> inline bool operator!=(IntrusiveReference<T> const & a, IntrusiveReference<U> const & b)
00156 {
00157    return a.getPtr() != b.getPtr();
00158 }
00159 template<class T> inline bool operator==(IntrusiveReference<T> const & a, T * b)
00160 {
00161    return a.getPtr() == b;
00162 }
00163 template<class T> inline bool operator!=(IntrusiveReference<T> const & a, T * b)
00164 {
00165    return a.getPtr() != b;
00166 }
00167 template<class T> inline bool operator==(T * a, IntrusiveReference<T> const & b)
00168 {
00169    return a == b.getPtr();
00170 }
00171 template<class T> inline bool operator!=(T * a, IntrusiveReference<T> const & b)
00172 {
00173    return a != b.getPtr();
00174 }
00175 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
00176 // Resolve the ambiguity between our op!= and the one in rel_ops
00177 template<class T> inline bool operator!=(IntrusiveReference<T> const & a, IntrusiveReference<T> const & b)
00178 {
00179    return a.getPtr() != b.getPtr();
00180 }
00181 #endif
00182 template<class T> inline bool operator<(IntrusiveReference<T> const & a, IntrusiveReference<T> const & b)
00183 {
00184    return a.getPtr() < b.getPtr();
00185 }
00186 template<class T> void swap(IntrusiveReference<T> & lhs, IntrusiveReference<T> & rhs)
00187 {
00188    lhs.swap(rhs);
00189 }
00190 template<class T, class U> IntrusiveReference<T> static_pointer_cast(IntrusiveReference<U> const & p)
00191 {
00192    return static_cast<T *>(p.getPtr());
00193 }
00194 template<class T, class U> IntrusiveReference<T> const_pointer_cast(IntrusiveReference<U> const & p)
00195 {
00196    return const_cast<T *>(p.getPtr());
00197 }
00198 template<class T, class U> IntrusiveReference<T> dynamic_pointer_cast(IntrusiveReference<U> const & p)
00199 {
00200    return dynamic_cast<T *>(p.getPtr());
00201 }
00202 
00203 } // end namespace BLOCXX_NAMESPACE
00204 
00205 #endif

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