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 00048 #ifndef BLOCXX_COW_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_ 00049 #define BLOCXX_COW_INTRUSIVE_REFERENCE_HPP_INCLUDE_GUARD_ 00050 00051 #include "blocxx/BLOCXX_config.h" 00052 #include "blocxx/ReferenceHelpers.hpp" 00053 00054 namespace BLOCXX_NAMESPACE 00055 { 00056 00083 template<class T> class COWIntrusiveReference 00084 { 00085 private: 00086 typedef COWIntrusiveReference this_type; 00087 public: 00088 typedef T element_type; 00089 00094 COWIntrusiveReference(): m_pObj(0) 00095 { 00096 } 00104 COWIntrusiveReference(T * p, bool addRef = true): m_pObj(p) 00105 { 00106 if (m_pObj != 0 && addRef) COWIntrusiveReferenceAddRef(m_pObj); 00107 } 00118 template<class U> COWIntrusiveReference(COWIntrusiveReference<U> const & rhs): m_pObj(rhs.m_pObj) 00119 { 00120 if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj); 00121 } 00130 COWIntrusiveReference(COWIntrusiveReference const & rhs): m_pObj(rhs.m_pObj) 00131 { 00132 if (m_pObj != 0) COWIntrusiveReferenceAddRef(m_pObj); 00133 } 00139 ~COWIntrusiveReference() 00140 { 00141 if (m_pObj != 0) COWIntrusiveReferenceRelease(m_pObj); 00142 } 00143 00155 template<class U> COWIntrusiveReference & operator=(COWIntrusiveReference<U> const & rhs) 00156 { 00157 this_type(rhs).swap(*this); 00158 return *this; 00159 } 00170 COWIntrusiveReference & operator=(COWIntrusiveReference const & rhs) 00171 { 00172 this_type(rhs).swap(*this); 00173 return *this; 00174 } 00183 COWIntrusiveReference & operator=(T * rhs) 00184 { 00185 this_type(rhs).swap(*this); 00186 return *this; 00187 } 00192 const T * getPtr() const 00193 { 00194 return m_pObj; 00195 } 00196 00201 const T & operator*() const 00202 { 00203 #ifdef BLOCXX_CHECK_NULL_REFERENCES 00204 ReferenceHelpers::checkNull(this); 00205 ReferenceHelpers::checkNull(m_pObj); 00206 #endif 00207 return *m_pObj; 00208 } 00209 00214 const T * operator->() const 00215 { 00216 #ifdef BLOCXX_CHECK_NULL_REFERENCES 00217 ReferenceHelpers::checkNull(this); 00218 ReferenceHelpers::checkNull(m_pObj); 00219 #endif 00220 return m_pObj; 00221 } 00222 00227 T & operator*() 00228 { 00229 #ifdef BLOCXX_CHECK_NULL_REFERENCES 00230 ReferenceHelpers::checkNull(this); 00231 ReferenceHelpers::checkNull(m_pObj); 00232 #endif 00233 getWriteLock(); 00234 return *m_pObj; 00235 } 00236 00241 T * operator->() 00242 { 00243 #ifdef BLOCXX_CHECK_NULL_REFERENCES 00244 ReferenceHelpers::checkNull(this); 00245 ReferenceHelpers::checkNull(m_pObj); 00246 #endif 00247 getWriteLock(); 00248 return m_pObj; 00249 } 00250 00251 typedef T * this_type::*unspecified_bool_type; 00252 operator unspecified_bool_type () const 00253 { 00254 return m_pObj == 0? 0: &this_type::m_pObj; 00255 } 00256 00262 bool operator! () const 00263 { 00264 return m_pObj == 0; 00265 } 00266 00267 void swap(COWIntrusiveReference & rhs) 00268 { 00269 T * tmp = m_pObj; 00270 m_pObj = rhs.m_pObj; 00271 rhs.m_pObj = tmp; 00272 } 00273 00274 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE 00275 /* This is so the templated constructor will work */ 00276 template <class U> friend class COWIntrusiveReference; 00277 private: 00278 #endif 00279 00285 void getWriteLock() 00286 { 00287 if ((m_pObj != 0) && !COWIntrusiveReferenceUnique(m_pObj)) 00288 { 00289 m_pObj = COWIntrusiveReferenceClone(m_pObj); 00290 } 00291 } 00292 00293 00294 T * m_pObj; 00295 }; 00296 template<class T, class U> inline bool operator==(COWIntrusiveReference<T> const & a, COWIntrusiveReference<U> const & b) 00297 { 00298 return a.getPtr() == b.getPtr(); 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> inline bool operator==(COWIntrusiveReference<T> const & a, const T * b) 00305 { 00306 return a.getPtr() == b; 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==(const T * a, COWIntrusiveReference<T> const & b) 00313 { 00314 return a == b.getPtr(); 00315 } 00316 template<class T> inline bool operator!=(const T * a, COWIntrusiveReference<T> const & b) 00317 { 00318 return a != b.getPtr(); 00319 } 00320 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 00321 // Resolve the ambiguity between our op!= and the one in rel_ops 00322 template<class T> inline bool operator!=(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b) 00323 { 00324 return a.getPtr() != b.getPtr(); 00325 } 00326 #endif 00327 template<class T> inline bool operator<(COWIntrusiveReference<T> const & a, COWIntrusiveReference<T> const & b) 00328 { 00329 return a.getPtr() < b.getPtr(); 00330 } 00331 template<class T> void swap(COWIntrusiveReference<T> & lhs, COWIntrusiveReference<T> & rhs) 00332 { 00333 lhs.swap(rhs); 00334 } 00335 00336 } // end namespace BLOCXX_NAMESPACE 00337 00338 #endif 00339