blocxx
|
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