Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

shared_ptr.h

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil c-basic-offset: 3 -*- */
00002 // vim:cindent:ts=3:sw=3:et:tw=80:sta:
00003 /*************************************************************** cppdom-cpr beg
00004  * 
00005  * cppdom was forked from the original xmlpp version 0.6 under the LGPL. This
00006  * new, branched xmlpp is under the same LGPL (of course) and is being
00007  * maintained by:
00008  *      Kevin Meinert   <subatomic@users.sourceforge.net>
00009  *      Allen Bierbaum  <allenb@users.sourceforge.net>
00010  *      Ben Scott       <nonchocoboy@users.sourceforge.net>
00011  *
00012  * -----------------------------------------------------------------
00013  *
00014  * xmlpp - an xml parser and validator written in C++
00015  * copyright (c) 2000-2001 Michael Fink
00016  *
00017  * This library is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU Library General Public
00019  * License as published by the Free Software Foundation; either
00020  * version 2 of the License, or (at your option) any later version.
00021  *
00022  * This library is distributed in the hope that it will be useful,
00023  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * Library General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU Library General Public
00028  * License along with this library; if not, write to the
00029  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00030  * Boston, MA 02111-1307, USA.
00031  *
00032  * -----------------------------------------------------------------
00033  * File:          $RCSfile: shared_ptr.h,v $
00034  * Date modified: $Date: 2003/01/03 02:37:47 $
00035  * Version:       $Revision: 1.11 $
00036  * -----------------------------------------------------------------
00037  *
00038  ************************************************************ cppdom-cpr-end */
00048 // prevent multiple includes
00049 #ifndef CPPDOM_SHARED_PTR_H
00050 #define CPPDOM_SHARED_PTR_H
00051 
00052 //  Boost smart_ptr.hpp header file  -----------------------------------------//
00053 
00054 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy,
00055 // use, modify, sell and distribute this software is granted provided this
00056 // copyright notice appears in all copies. This software is provided "as is"
00057 // without express or implied warranty, and with no claim as to its
00058 // suitability for any purpose.
00059 
00060 // needed includes
00061 //#include <cstddef>            // for std::size_t
00062 #include <memory>             // for std::auto_ptr
00063 #include <algorithm>          // for std::swap
00064 #include <functional>         // for std::less
00065 
00067 namespace cppdom_boost {
00068 
00069    template< typename T >
00070     inline void checked_delete(T * x)
00071     {
00072         delete x;
00073     }
00074 
00075     template< typename T >
00076     inline void checked_array_delete(T  * x)
00077     {
00078         delete [] x;
00079     }
00080 
00081 namespace detail {
00082 
00083 template<typename T> struct shared_deleter
00084 {
00085    static void del(T * p)
00086    {
00087       checked_delete(p);
00088    }
00089 };
00090 
00091 struct dynamic_cast_tag {};
00092 
00093 template<class T> struct shared_ptr_traits
00094 {
00095    typedef T & reference;
00096 };
00097 
00098 template<> struct shared_ptr_traits<void>
00099 {
00100    typedef void reference;
00101 };
00102 
00103 } // namespace detail
00104 
00105 // shared_ptr --------------------------------------------------------------//
00106 
00108 
00112 template<typename T> class shared_ptr {
00113   public:
00114    typedef T element_type;
00115 
00116    explicit shared_ptr(T* p =0) : px(p) {
00117       try { pn = new long(1); }  // fix: prevent leak if new throws
00118       catch (...) { delete p; throw; } 
00119    }
00120 
00121    shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); }  // never throws
00122 
00123    ~shared_ptr() { dispose(); }
00124 
00125    shared_ptr& operator=(const shared_ptr& r) {
00126       share(r.px,r.pn);
00127       return *this;
00128    }
00129 
00130 #if !defined( BOOST_NO_MEMBER_TEMPLATES )
00131    template<typename Y>
00132       shared_ptr(const shared_ptr<Y>& r) : px(r.px) {  // never throws 
00133          ++*(pn = r.pn); 
00134       }
00135 
00136    template<typename Y>
00137       shared_ptr(std::auto_ptr<Y>& r) { 
00138          pn = new long(1); // may throw
00139          px = r.release(); // fix: moved here to stop leak if new throws
00140       } 
00141 
00142    template<typename Y>
00143       shared_ptr& operator=(const shared_ptr<Y>& r) { 
00144          share(r.px,r.pn);
00145          return *this;
00146       }
00147 
00148    template<typename Y>
00149       shared_ptr& operator=(std::auto_ptr<Y>& r) {
00150          // code choice driven by guarantee of "no effect if new throws"
00151          if (*pn == 1) { delete px; }
00152          else { // allocate new reference counter
00153            long * tmp = new long(1); // may throw
00154            --*pn; // only decrement once danger of new throwing is past
00155            pn = tmp;
00156          } // allocate new reference counter
00157          px = r.release(); // fix: moved here so doesn't leak if new throws 
00158          return *this;
00159       }
00160 #else
00161       shared_ptr(std::auto_ptr<T>& r) { 
00162          pn = new long(1); // may throw
00163          px = r.release(); // fix: moved here to stop leak if new throws
00164       } 
00165 
00166       shared_ptr& operator=(std::auto_ptr<T>& r) {
00167          // code choice driven by guarantee of "no effect if new throws"
00168          if (*pn == 1) { delete px; }
00169          else { // allocate new reference counter
00170            long * tmp = new long(1); // may throw
00171            --*pn; // only decrement once danger of new throwing is past
00172            pn = tmp;
00173          } // allocate new reference counter
00174          px = r.release(); // fix: moved here so doesn't leak if new throws 
00175          return *this;
00176       }
00177 #endif
00178 
00179    void reset(T* p=0) {
00180       if ( px == p ) return;  // fix: self-assignment safe
00181       if (--*pn == 0) { delete px; }
00182       else { // allocate new reference counter
00183         try { pn = new long; }  // fix: prevent leak if new throws
00184         catch (...) {
00185           ++*pn;  // undo effect of --*pn above to meet effects guarantee 
00186           delete p;
00187           throw;
00188         } // catch
00189       } // allocate new reference counter
00190       *pn = 1;
00191       px = p;
00192    } // reset
00193 
00194    T& operator*() const          { return *px; }  // never throws
00195    T* operator->() const         { return px; }  // never throws
00196    T* get() const                { return px; }  // never throws
00197  #ifdef BOOST_SMART_PTR_CONVERSION
00198    // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
00199    operator T*() const           { return px; }  // never throws 
00200  #endif
00201 
00202    long use_count() const        { return *pn; }  // never throws
00203    bool unique() const           { return *pn == 1; }  // never throws
00204 
00205    void swap(shared_ptr<T>& other)  // never throws
00206      { std::swap(px,other.px); std::swap(pn,other.pn); }
00207 
00208 // Tasteless as this may seem, making all members public allows member templates
00209 // to work in the absence of member template friends. (Matthew Langston)
00210 // Don't split this line into two; that causes problems for some GCC 2.95.2 builds
00211 #if defined(BOOST_NO_MEMBER_TEMPLATES) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
00212    private:
00213 #endif
00214 
00215    T*     px;     // contained pointer
00216    long*  pn;     // ptr to reference counter
00217 
00218 // Don't split this line into two; that causes problems for some GCC 2.95.2 builds
00219 #if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
00220    template<typename Y> friend class shared_ptr;
00221 #endif
00222 
00223    void dispose() { if (--*pn == 0) { delete px; delete pn; } }
00224 
00225    void share(T* rpx, long* rpn) {
00226       if (pn != rpn) {
00227          dispose();
00228          px = rpx;
00229          ++*(pn = rpn);
00230       }
00231    } // share
00232 };  // shared_ptr
00233 
00234 template<typename T, typename U>
00235   inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
00236     { return a.get() == b.get(); }
00237 
00238 template<typename T, typename U>
00239   inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
00240     { return a.get() != b.get(); }
00241 /*
00242 template<class _K, class _Pr, class _A> inline
00243    bool operator!=(const set<_K, _Pr, _A>& _X,
00244       const set<_K, _Pr, _A>& _Y)
00245    {return (!(_X == _Y)); }
00246 */
00247 
00248 template<typename T> inline bool operator<(shared_ptr<T> const& a,
00249                                            shared_ptr<T> const& b)
00250 {
00251    return std::less<T*>()(a.get(), b.get());
00252 }
00253 
00254 template<typename T, typename U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
00255 {
00256    return shared_ptr<T>(r, detail::dynamic_cast_tag());
00257 }
00258 
00259 } // namespace boost
00260 
00261 
00262 //  specializations for things in namespace std  ---------------------------//
00263 
00264 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
00265 
00266 namespace std {
00267 
00268 // Specialize std::swap to use the fast, non-throwing swap that's provided
00269 // as a member function instead of using the default algorithm which creates
00270 // a temporary and uses assignment.
00271 
00272 template<typename T>
00273   inline void swap(cppdom_boost::shared_ptr<T>& a, cppdom_boost::shared_ptr<T>& b)
00274     { a.swap(b); }
00275 
00276 } // namespace std
00277 
00278 #endif
00279 
00280 #endif

Generated on Thu Jan 2 21:29:17 2003 for cppdom by doxygen1.2.15