blocxx

COWIntrusiveReference.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 
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