boost_shared_ptr.h

Go to the documentation of this file.
00001 // <tr1/boost_shared_ptr.h> -*- C++ -*-
00002 
00003 // Copyright (C) 2005, 2006 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License along
00017 // with this library; see the file COPYING.  If not, write to the Free
00018 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00019 // USA.
00020 
00021 // As a special exception, you may use this file as part of a free software
00022 // library without restriction.  Specifically, if other files instantiate
00023 // templates or use macros or inline functions from this file, or you compile
00024 // this file and link it with other files to produce an executable, this
00025 // file does not by itself cause the resulting executable to be covered by
00026 // the GNU General Public License.  This exception does not however
00027 // invalidate any other reasons why the executable file might be covered by
00028 // the GNU General Public License.
00029 
00030 //  shared_count.hpp
00031 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
00032 
00033 //  shared_ptr.hpp
00034 //  Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
00035 //  Copyright (C) 2001, 2002, 2003 Peter Dimov
00036 
00037 //  weak_ptr.hpp
00038 //  Copyright (C) 2001, 2002, 2003 Peter Dimov
00039 
00040 //  enable_shared_from_this.hpp
00041 //  Copyright (C) 2002 Peter Dimov
00042 
00043 // Distributed under the Boost Software License, Version 1.0. (See
00044 // accompanying file LICENSE_1_0.txt or copy at
00045 // http://www.boost.org/LICENSE_1_0.txt)
00046 
00047 // GCC Note:  based on version 1.32.0 of the Boost library.
00048 
00049 /** @file tr1/boost_shared_ptr.h
00050  *  This is an internal header file, included by other library headers.
00051  *  You should not attempt to use it directly.
00052  */
00053 
00054 #ifndef _BOOST_SHARED_PTR_H
00055 #define _BOOST_SHARED_PTR_H 1
00056 
00057 namespace std
00058 {
00059 _GLIBCXX_BEGIN_NAMESPACE(tr1)
00060 
00061   class bad_weak_ptr : public std::exception
00062   {
00063   public:
00064     virtual char const*
00065     what() const throw()
00066     { return "tr1::bad_weak_ptr"; }
00067   };
00068 
00069   // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
00070   inline void
00071   __throw_bad_weak_ptr()
00072   {
00073 #if __EXCEPTIONS
00074     throw bad_weak_ptr();
00075 #else
00076     std::abort();
00077 #endif
00078   }
00079 
00080   using __gnu_cxx::_Lock_policy;
00081   using __gnu_cxx::__default_lock_policy;
00082   using __gnu_cxx::_S_single;
00083   using __gnu_cxx::_S_mutex;
00084   using __gnu_cxx::_S_atomic;
00085 
00086   template<typename _Tp>
00087     struct _Sp_deleter
00088     {
00089       typedef void result_type;
00090       typedef _Tp* argument_type;
00091 
00092       void
00093       operator()(_Tp* __p) const
00094       { delete __p; }
00095     };
00096 
00097   // Empty helper class except when the template argument is _S_mutex.
00098   template<_Lock_policy _Lp>
00099     class _Mutex_base
00100     { };
00101 
00102   template<>
00103     class _Mutex_base<_S_mutex>
00104     : public __gnu_cxx::__mutex
00105     { };
00106 
00107   template<_Lock_policy _Lp = __default_lock_policy>
00108     class _Sp_counted_base
00109     : public _Mutex_base<_Lp>
00110     {
00111     public:  
00112       _Sp_counted_base()
00113       : _M_use_count(1), _M_weak_count(1) { }
00114       
00115       virtual
00116       ~_Sp_counted_base() // nothrow 
00117       { }
00118   
00119       // Called when _M_use_count drops to zero, to release the resources
00120       // managed by *this.
00121       virtual void
00122       _M_dispose() = 0; // nothrow
00123       
00124       // Called when _M_weak_count drops to zero.
00125       virtual void
00126       _M_destroy() // nothrow
00127       { delete this; }
00128       
00129       virtual void*
00130       _M_get_deleter(const std::type_info&) = 0;
00131 
00132       void
00133       _M_add_ref_copy()
00134       { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
00135   
00136       void
00137       _M_add_ref_lock();
00138       
00139       void
00140       _M_release() // nothrow
00141       {
00142     if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count,
00143                            -1) == 1)
00144       {
00145         _M_dispose();
00146 #ifdef __GTHREADS
00147         _GLIBCXX_READ_MEM_BARRIER;
00148         _GLIBCXX_WRITE_MEM_BARRIER;
00149 #endif
00150         if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
00151                                -1) == 1)
00152           _M_destroy();
00153       }
00154       }
00155   
00156       void
00157       _M_weak_add_ref() // nothrow
00158       { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
00159 
00160       void
00161       _M_weak_release() // nothrow
00162       {
00163     if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
00164       {
00165 #ifdef __GTHREADS
00166         _GLIBCXX_READ_MEM_BARRIER;
00167         _GLIBCXX_WRITE_MEM_BARRIER;
00168 #endif
00169         _M_destroy();
00170       }
00171       }
00172   
00173       long
00174       _M_get_use_count() const // nothrow
00175       { return _M_use_count; }  // XXX is this MT safe? 
00176       
00177     private:  
00178       _Sp_counted_base(_Sp_counted_base const&);
00179       _Sp_counted_base& operator=(_Sp_counted_base const&);
00180 
00181       _Atomic_word  _M_use_count;     // #shared
00182       _Atomic_word  _M_weak_count;    // #weak + (#shared != 0)
00183     };
00184 
00185   template<>
00186     inline void
00187     _Sp_counted_base<_S_single>::
00188     _M_add_ref_lock()
00189     {
00190       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
00191     {
00192       _M_use_count = 0;
00193       __throw_bad_weak_ptr();
00194     }
00195     }
00196 
00197 #ifdef __GTHREADS
00198   template<>
00199     inline void
00200     _Sp_counted_base<_S_mutex>::
00201     _M_add_ref_lock()
00202     {
00203       __gnu_cxx::__scoped_lock sentry(*this);
00204       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
00205     {
00206       _M_use_count = 0;
00207       __throw_bad_weak_ptr();
00208     }
00209     }
00210 #endif
00211 
00212   template<> 
00213     inline void
00214     _Sp_counted_base<_S_atomic>::
00215     _M_add_ref_lock()
00216     {
00217       // Perform lock-free add-if-not-zero operation.
00218       _Atomic_word __count;
00219       do
00220     {
00221       __count = _M_use_count;
00222       if (__count == 0)
00223         __throw_bad_weak_ptr();
00224       
00225       // Replace the current counter value with the old value + 1, as
00226       // long as it's not changed meanwhile. 
00227     }
00228       while (!__sync_bool_compare_and_swap(&_M_use_count, __count,
00229                        __count + 1));
00230     }
00231 
00232   template<typename _Ptr, typename _Deleter, _Lock_policy _Lp>
00233     class _Sp_counted_base_impl
00234     : public _Sp_counted_base<_Lp>
00235     {
00236     public:
00237       /**
00238        *  @brief   
00239        *  @pre     __d(__p) must not throw.
00240        */
00241       _Sp_counted_base_impl(_Ptr __p, _Deleter __d)
00242       : _M_ptr(__p), _M_del(__d) { }
00243     
00244       virtual void
00245       _M_dispose() // nothrow
00246       { _M_del(_M_ptr); }
00247       
00248       virtual void*
00249       _M_get_deleter(const std::type_info& __ti)
00250       { return __ti == typeid(_Deleter) ? &_M_del : 0; }
00251       
00252     private:
00253       _Sp_counted_base_impl(const _Sp_counted_base_impl&);
00254       _Sp_counted_base_impl& operator=(const _Sp_counted_base_impl&);
00255       
00256       _Ptr      _M_ptr;  // copy constructor must not throw
00257       _Deleter  _M_del;  // copy constructor must not throw
00258     };
00259 
00260   template<_Lock_policy _Lp = __default_lock_policy>
00261     class __weak_count;
00262 
00263   template<_Lock_policy _Lp = __default_lock_policy>
00264     class __shared_count
00265     {
00266     public: 
00267       __shared_count()
00268       : _M_pi(0) // nothrow
00269       { }
00270   
00271       template<typename _Ptr, typename _Deleter>
00272         __shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
00273         {
00274       try
00275         {
00276           _M_pi = new _Sp_counted_base_impl<_Ptr, _Deleter, _Lp>(__p, __d);
00277         }
00278       catch(...)
00279         {
00280           __d(__p); // Call _Deleter on __p.
00281           __throw_exception_again;
00282         }
00283     }
00284 
00285       // Special case for auto_ptr<_Tp> to provide the strong guarantee.
00286       template<typename _Tp>
00287         explicit
00288         __shared_count(std::auto_ptr<_Tp>& __r)
00289     : _M_pi(new _Sp_counted_base_impl<_Tp*,
00290         _Sp_deleter<_Tp>, _Lp >(__r.get(), _Sp_deleter<_Tp>()))
00291         { __r.release(); }
00292   
00293       // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
00294       explicit
00295       __shared_count(const __weak_count<_Lp>& __r);
00296   
00297       ~__shared_count() // nothrow
00298       {
00299     if (_M_pi != 0)
00300       _M_pi->_M_release();
00301       }
00302       
00303       __shared_count(const __shared_count& __r)
00304       : _M_pi(__r._M_pi) // nothrow
00305       {
00306     if (_M_pi != 0)
00307       _M_pi->_M_add_ref_copy();
00308       }
00309   
00310       __shared_count&
00311       operator=(const __shared_count& __r) // nothrow
00312       {
00313     _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
00314     if (__tmp != _M_pi)
00315       {
00316         if (__tmp != 0)
00317           __tmp->_M_add_ref_copy();
00318         if (_M_pi != 0)
00319           _M_pi->_M_release();
00320         _M_pi = __tmp;
00321       }
00322     return *this;
00323       }
00324   
00325       void
00326       _M_swap(__shared_count& __r) // nothrow
00327       {
00328     _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
00329     __r._M_pi = _M_pi;
00330     _M_pi = __tmp;
00331       }
00332   
00333       long
00334       _M_get_use_count() const // nothrow
00335       { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
00336 
00337       bool
00338       _M_unique() const // nothrow
00339       { return this->_M_get_use_count() == 1; }
00340       
00341       friend inline bool
00342       operator==(const __shared_count& __a, const __shared_count& __b)
00343       { return __a._M_pi == __b._M_pi; }
00344   
00345       friend inline bool
00346       operator<(const __shared_count& __a, const __shared_count& __b)
00347       { return std::less<_Sp_counted_base<_Lp>*>()(__a._M_pi, __b._M_pi); }
00348   
00349       void*
00350       _M_get_deleter(const std::type_info& __ti) const
00351       { return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0; }
00352 
00353     private:
00354       friend class __weak_count<_Lp>;
00355 
00356       _Sp_counted_base<_Lp>*  _M_pi;
00357     };
00358 
00359   template<_Lock_policy _Lp>
00360     class __weak_count
00361     {
00362     public:
00363       __weak_count()
00364       : _M_pi(0) // nothrow
00365       { }
00366   
00367       __weak_count(const __shared_count<_Lp>& __r)
00368       : _M_pi(__r._M_pi) // nothrow
00369       {
00370     if (_M_pi != 0)
00371       _M_pi->_M_weak_add_ref();
00372       }
00373       
00374       __weak_count(const __weak_count<_Lp>& __r)
00375       : _M_pi(__r._M_pi) // nothrow
00376       {
00377     if (_M_pi != 0)
00378       _M_pi->_M_weak_add_ref();
00379       }
00380       
00381       ~__weak_count() // nothrow
00382       {
00383     if (_M_pi != 0)
00384       _M_pi->_M_weak_release();
00385       }
00386       
00387       __weak_count<_Lp>&
00388       operator=(const __shared_count<_Lp>& __r) // nothrow
00389       {
00390     _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
00391     if (__tmp != 0)
00392       __tmp->_M_weak_add_ref();
00393     if (_M_pi != 0)
00394       _M_pi->_M_weak_release();
00395     _M_pi = __tmp;  
00396     return *this;
00397       }
00398       
00399       __weak_count<_Lp>&
00400       operator=(const __weak_count<_Lp>& __r) // nothrow
00401       {
00402     _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
00403     if (__tmp != 0)
00404       __tmp->_M_weak_add_ref();
00405     if (_M_pi != 0)
00406       _M_pi->_M_weak_release();
00407     _M_pi = __tmp;
00408     return *this;
00409       }
00410 
00411       void
00412       _M_swap(__weak_count<_Lp>& __r) // nothrow
00413       {
00414     _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
00415     __r._M_pi = _M_pi;
00416     _M_pi = __tmp;
00417       }
00418   
00419       long
00420       _M_get_use_count() const // nothrow
00421       { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
00422 
00423       friend inline bool
00424       operator==(const __weak_count<_Lp>& __a, const __weak_count<_Lp>& __b)
00425       { return __a._M_pi == __b._M_pi; }
00426       
00427       friend inline bool
00428       operator<(const __weak_count<_Lp>& __a, const __weak_count<_Lp>& __b)
00429       { return std::less<_Sp_counted_base<_Lp>*>()(__a._M_pi, __b._M_pi); }
00430 
00431     private:
00432       friend class __shared_count<_Lp>;
00433 
00434       _Sp_counted_base<_Lp>*  _M_pi;
00435     };
00436 
00437   template<_Lock_policy _Lp>
00438     inline
00439     __shared_count<_Lp>::
00440     __shared_count(const __weak_count<_Lp>& __r)
00441     : _M_pi(__r._M_pi)
00442     {
00443       if (_M_pi != 0)
00444     _M_pi->_M_add_ref_lock();
00445       else
00446     __throw_bad_weak_ptr();
00447     }
00448   
00449 
00450   // Forward declarations.
00451   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
00452     class __shared_ptr;
00453   
00454   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
00455     class __weak_ptr;
00456 
00457   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
00458     class __enable_shared_from_this;
00459 
00460   template<typename _Tp>
00461     class shared_ptr;
00462   
00463   template<typename _Tp>
00464     class weak_ptr;
00465 
00466   template<typename _Tp>
00467     class enable_shared_from_this;
00468 
00469   // Support for enable_shared_from_this.
00470 
00471   // Friend of __enable_shared_from_this.
00472   template<_Lock_policy _Lp, typename _Tp1, typename _Tp2>
00473     void
00474     __enable_shared_from_this_helper(const __shared_count<_Lp>&,
00475                      const __enable_shared_from_this<_Tp1,
00476                      _Lp>*, const _Tp2*);
00477 
00478   // Friend of enable_shared_from_this.
00479   template<typename _Tp1, typename _Tp2>
00480     void
00481     __enable_shared_from_this_helper(const __shared_count<>&,
00482                      const enable_shared_from_this<_Tp1>*,
00483                      const _Tp2*);
00484 
00485   template<_Lock_policy _Lp>
00486     inline void
00487     __enable_shared_from_this_helper(const __shared_count<_Lp>&, ...)
00488     { }
00489 
00490 
00491   struct __static_cast_tag { };
00492   struct __const_cast_tag { };
00493   struct __dynamic_cast_tag { };
00494 
00495   /**
00496    *  @class shared_ptr <tr1/memory>
00497    *
00498    *  A smart pointer with reference-counted copy semantics.
00499    *  The object pointed to is deleted when the last shared_ptr pointing to
00500    *  it is destroyed or reset.
00501    */
00502   template<typename _Tp, _Lock_policy _Lp>
00503     class __shared_ptr
00504     {
00505     public:
00506       typedef _Tp   element_type;
00507       
00508       /** @brief  Construct an empty %__shared_ptr.
00509        *  @post   use_count()==0 && get()==0
00510        */
00511       __shared_ptr()
00512       : _M_ptr(0), _M_refcount() // never throws
00513       { }
00514 
00515       /** @brief  Construct a %__shared_ptr that owns the pointer @a __p.
00516        *  @param  __p  A pointer that is convertible to element_type*.
00517        *  @post   use_count() == 1 && get() == __p
00518        *  @throw  std::bad_alloc, in which case @c delete @a __p is called.
00519        */
00520       template<typename _Tp1>
00521         explicit
00522         __shared_ptr(_Tp1* __p)
00523     : _M_ptr(__p), _M_refcount(__p, _Sp_deleter<_Tp1>())
00524         {
00525       __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
00526       // __glibcxx_function_requires(_CompleteConcept<_Tp1*>)
00527       __enable_shared_from_this_helper(_M_refcount, __p, __p);
00528     }
00529 
00530       //
00531       // Requirements: _Deleter' copy constructor and destructor must not throw
00532       //
00533       // __shared_ptr will release __p by calling __d(__p)
00534       //
00535       /** @brief  Construct a %__shared_ptr that owns the pointer @a __p
00536        *          and the deleter @a __d.
00537        *  @param  __p  A pointer.
00538        *  @param  __d  A deleter.
00539        *  @post   use_count() == 1 && get() == __p
00540        *  @throw  std::bad_alloc, in which case @a __d(__p) is called.
00541        */
00542       template<typename _Tp1, typename _Deleter>
00543         __shared_ptr(_Tp1* __p, _Deleter __d)
00544     : _M_ptr(__p), _M_refcount(__p, __d)
00545         {
00546       __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
00547       // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
00548       __enable_shared_from_this_helper(_M_refcount, __p, __p);
00549     }
00550       
00551       //  generated copy constructor, assignment, destructor are fine.
00552       
00553       /** @brief  If @a __r is empty, constructs an empty %__shared_ptr;
00554        *          otherwise construct a %__shared_ptr that shares ownership
00555        *          with @a __r.
00556        *  @param  __r  A %__shared_ptr.
00557        *  @post   get() == __r.get() && use_count() == __r.use_count()
00558        *  @throw  std::bad_alloc, in which case 
00559        */
00560       template<typename _Tp1>
00561         __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r)
00562     : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
00563         { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) }
00564 
00565       /** @brief  Constructs a %__shared_ptr that shares ownership with @a __r
00566        *          and stores a copy of the pointer stored in @a __r.
00567        *  @param  __r  A weak_ptr.
00568        *  @post   use_count() == __r.use_count()
00569        *  @throw  bad_weak_ptr when __r.expired(),
00570        *          in which case the constructor has no effect.
00571        */
00572       template<typename _Tp1>
00573         explicit
00574         __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
00575     : _M_refcount(__r._M_refcount) // may throw
00576         {
00577       __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
00578       // It is now safe to copy __r._M_ptr, as _M_refcount(__r._M_refcount)
00579       // did not throw.
00580       _M_ptr = __r._M_ptr;
00581     }
00582 
00583       /**
00584        * @post use_count() == 1 and __r.get() == 0
00585        */
00586       template<typename _Tp1>
00587         explicit
00588         __shared_ptr(std::auto_ptr<_Tp1>& __r)
00589     : _M_ptr(__r.get()), _M_refcount()
00590         {
00591       // TODO requires __r.release() convertible to _Tp*, _Tp1 is complete,
00592       // delete __r.release() well-formed
00593       _Tp1* __tmp = __r.get();
00594       _M_refcount = __shared_count<_Lp>(__r);
00595       __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp);
00596     }
00597 
00598       template<typename _Tp1>
00599         __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __static_cast_tag)
00600     : _M_ptr(static_cast<element_type*>(__r._M_ptr)),
00601       _M_refcount(__r._M_refcount)
00602         { }
00603 
00604       template<typename _Tp1>
00605         __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __const_cast_tag)
00606     : _M_ptr(const_cast<element_type*>(__r._M_ptr)),
00607       _M_refcount(__r._M_refcount)
00608         { }
00609 
00610       template<typename _Tp1>
00611         __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __dynamic_cast_tag)
00612     : _M_ptr(dynamic_cast<element_type*>(__r._M_ptr)),
00613       _M_refcount(__r._M_refcount)
00614         {
00615       if (_M_ptr == 0) // need to allocate new counter -- the cast failed
00616         _M_refcount = __shared_count<_Lp>();
00617     }
00618       
00619       template<typename _Tp1>
00620         __shared_ptr&
00621         operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws
00622         {
00623       _M_ptr = __r._M_ptr;
00624       _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
00625       return *this;
00626     }
00627 
00628       template<typename _Tp1>
00629         __shared_ptr&
00630         operator=(std::auto_ptr<_Tp1>& __r)
00631         {
00632       __shared_ptr(__r).swap(*this);
00633       return *this;
00634     }
00635 
00636       void
00637       reset() // never throws
00638       { __shared_ptr().swap(*this); }
00639 
00640       template<typename _Tp1>
00641         void
00642         reset(_Tp1* __p) // _Tp1 must be complete.
00643         {
00644       // Catch self-reset errors.
00645       _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr); 
00646       __shared_ptr(__p).swap(*this);
00647     }
00648 
00649       template<typename _Tp1, typename _Deleter>
00650         void
00651         reset(_Tp1* __p, _Deleter __d)
00652         { __shared_ptr(__p, __d).swap(*this); }
00653 
00654       // Allow class instantiation when _Tp is [cv-qual] void.
00655       typename add_reference<_Tp>::type
00656       operator*() const // never throws
00657       {
00658     _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
00659     return *_M_ptr;
00660       }
00661 
00662       _Tp*
00663       operator->() const // never throws
00664       {
00665     _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
00666     return _M_ptr;
00667       }
00668     
00669       _Tp*
00670       get() const // never throws
00671       { return _M_ptr; }
00672 
00673       // Implicit conversion to "bool"
00674     private:
00675       typedef _Tp* __shared_ptr::*__unspecified_bool_type;
00676 
00677     public:
00678       operator __unspecified_bool_type() const // never throws
00679       { return _M_ptr == 0 ? 0 : &__shared_ptr::_M_ptr; }
00680 
00681       bool
00682       unique() const // never throws
00683       { return _M_refcount._M_unique(); }
00684 
00685       long
00686       use_count() const // never throws
00687       { return _M_refcount._M_get_use_count(); }
00688 
00689       void
00690       swap(__shared_ptr<_Tp, _Lp>& __other) // never throws
00691       {
00692     std::swap(_M_ptr, __other._M_ptr);
00693     _M_refcount._M_swap(__other._M_refcount);
00694       }
00695 
00696     private:
00697       void*
00698       _M_get_deleter(const std::type_info& __ti) const
00699       { return _M_refcount._M_get_deleter(__ti); }
00700 
00701       template<typename _Tp1, _Lock_policy _Lp1>
00702         bool
00703         _M_less(const __shared_ptr<_Tp1, _Lp1>& __rhs) const
00704         { return _M_refcount < __rhs._M_refcount; }
00705 
00706       template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
00707       template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
00708 
00709       template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
00710         friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&);
00711 
00712       // Friends injected into enclosing namespace and found by ADL:
00713       template<typename _Tp1>
00714         friend inline bool
00715         operator==(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
00716         { return __a.get() == __b.get(); }
00717 
00718       template<typename _Tp1>
00719         friend inline bool
00720         operator!=(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
00721         { return __a.get() != __b.get(); }
00722 
00723       template<typename _Tp1>
00724         friend inline bool
00725         operator<(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
00726         { return __a._M_less(__b); }
00727 
00728       _Tp*             _M_ptr;         // Contained pointer.
00729       __shared_count<_Lp>  _M_refcount;    // Reference counter.
00730     };
00731 
00732   // 2.2.3.8 shared_ptr specialized algorithms.
00733   template<typename _Tp, _Lock_policy _Lp>
00734     inline void
00735     swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b)
00736     { __a.swap(__b); }
00737 
00738   // 2.2.3.9 shared_ptr casts
00739   /** @warning The seemingly equivalent
00740    *           <code>shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))</code>
00741    *           will eventually result in undefined behaviour,
00742    *           attempting to delete the same object twice.
00743    */
00744   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
00745     __shared_ptr<_Tp, _Lp>
00746     static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r)
00747     { return __shared_ptr<_Tp, _Lp>(__r, __static_cast_tag()); }
00748 
00749   /** @warning The seemingly equivalent
00750    *           <code>shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))</code>
00751    *           will eventually result in undefined behaviour,
00752    *           attempting to delete the same object twice.
00753    */
00754   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
00755     __shared_ptr<_Tp, _Lp>
00756     const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r)
00757     { return __shared_ptr<_Tp, _Lp>(__r, __const_cast_tag()); }
00758 
00759   /** @warning The seemingly equivalent
00760    *           <code>shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))</code>
00761    *           will eventually result in undefined behaviour,
00762    *           attempting to delete the same object twice.
00763    */
00764   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
00765     __shared_ptr<_Tp, _Lp>
00766     dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r)
00767     { return __shared_ptr<_Tp, _Lp>(__r, __dynamic_cast_tag()); }
00768 
00769   // 2.2.3.7 shared_ptr I/O
00770   template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
00771     std::basic_ostream<_Ch, _Tr>&
00772     operator<<(std::basic_ostream<_Ch, _Tr>& __os, 
00773            const __shared_ptr<_Tp, _Lp>& __p)
00774     {
00775       __os << __p.get();
00776       return __os;
00777     }
00778 
00779   // 2.2.3.10 shared_ptr get_deleter (experimental)
00780   template<typename _Del, typename _Tp, _Lock_policy _Lp>
00781     inline _Del*
00782     get_deleter(const __shared_ptr<_Tp, _Lp>& __p)
00783     { return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del))); }
00784 
00785 
00786   template<typename _Tp, _Lock_policy _Lp>
00787     class __weak_ptr
00788     {
00789     public:
00790       typedef _Tp element_type;
00791       
00792       __weak_ptr()
00793       : _M_ptr(0), _M_refcount() // never throws
00794       { }
00795 
00796       // Generated copy constructor, assignment, destructor are fine.
00797       
00798       // The "obvious" converting constructor implementation:
00799       //
00800       //  template<typename _Tp1>
00801       //    __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
00802       //    : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
00803       //    { }
00804       //
00805       // has a serious problem.
00806       //
00807       //  __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
00808       //  conversion may require access to *__r._M_ptr (virtual inheritance).
00809       //
00810       // It is not possible to avoid spurious access violations since
00811       // in multithreaded programs __r._M_ptr may be invalidated at any point.
00812       template<typename _Tp1>
00813         __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
00814     : _M_refcount(__r._M_refcount) // never throws
00815         {
00816       __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
00817       _M_ptr = __r.lock().get();
00818     }
00819 
00820       template<typename _Tp1>
00821         __weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r)
00822     : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
00823         { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) }
00824 
00825       template<typename _Tp1>
00826         __weak_ptr&
00827         operator=(const __weak_ptr<_Tp1, _Lp>& __r) // never throws
00828         {
00829       _M_ptr = __r.lock().get();
00830       _M_refcount = __r._M_refcount;
00831       return *this;
00832     }
00833       
00834       template<typename _Tp1>
00835         __weak_ptr&
00836         operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws
00837         {
00838       _M_ptr = __r._M_ptr;
00839       _M_refcount = __r._M_refcount;
00840       return *this;
00841     }
00842 
00843       __shared_ptr<_Tp, _Lp>
00844       lock() const // never throws
00845       {
00846 #ifdef __GTHREADS
00847     // Optimization: avoid throw overhead.
00848     if (expired())
00849       return __shared_ptr<element_type, _Lp>();
00850 
00851     try
00852       {
00853         return __shared_ptr<element_type, _Lp>(*this);
00854       }
00855     catch(const bad_weak_ptr&)
00856       {
00857         // Q: How can we get here?
00858         // A: Another thread may have invalidated r after the
00859         //    use_count test above.
00860         return __shared_ptr<element_type, _Lp>();
00861       }
00862     
00863 #else
00864     // Optimization: avoid try/catch overhead when single threaded.
00865     return expired() ? __shared_ptr<element_type, _Lp>()
00866                      : __shared_ptr<element_type, _Lp>(*this);
00867 
00868 #endif
00869       } // XXX MT
00870 
00871       long
00872       use_count() const // never throws
00873       { return _M_refcount._M_get_use_count(); }
00874 
00875       bool
00876       expired() const // never throws
00877       { return _M_refcount._M_get_use_count() == 0; }
00878       
00879       void
00880       reset() // never throws
00881       { __weak_ptr().swap(*this); }
00882 
00883       void
00884       swap(__weak_ptr& __s) // never throws
00885       {
00886     std::swap(_M_ptr, __s._M_ptr);
00887     _M_refcount._M_swap(__s._M_refcount);
00888       }
00889 
00890     private:
00891       // Used by __enable_shared_from_this.
00892       void
00893       _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount)
00894       {
00895     _M_ptr = __ptr;
00896     _M_refcount = __refcount;
00897       }
00898 
00899       template<typename _Tp1>
00900         bool
00901         _M_less(const __weak_ptr<_Tp1, _Lp>& __rhs) const
00902         { return _M_refcount < __rhs._M_refcount; }
00903 
00904       template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
00905       template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
00906       friend class __enable_shared_from_this<_Tp, _Lp>;
00907       friend class enable_shared_from_this<_Tp>;
00908 
00909       // Friend injected into namespace and found by ADL.
00910       template<typename _Tp1>
00911         friend inline bool
00912         operator<(const __weak_ptr& __lhs, const __weak_ptr<_Tp1, _Lp>& __rhs)
00913         { return __lhs._M_less(__rhs); }
00914 
00915       _Tp*           _M_ptr;         // Contained pointer.
00916       __weak_count<_Lp>  _M_refcount;    // Reference counter.
00917     };
00918 
00919   // 2.2.4.7 weak_ptr specialized algorithms.
00920   template<typename _Tp, _Lock_policy _Lp>
00921     inline void
00922     swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b)
00923     { __a.swap(__b); }
00924 
00925 
00926   template<typename _Tp, _Lock_policy _Lp>
00927     class __enable_shared_from_this
00928     {
00929     protected:
00930       __enable_shared_from_this() { }
00931       
00932       __enable_shared_from_this(const __enable_shared_from_this&) { }
00933       
00934       __enable_shared_from_this&
00935       operator=(const __enable_shared_from_this&)
00936       { return *this; }
00937 
00938       ~__enable_shared_from_this() { }
00939       
00940     public:
00941       __shared_ptr<_Tp, _Lp>
00942       shared_from_this()
00943       { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
00944 
00945       __shared_ptr<const _Tp, _Lp>
00946       shared_from_this() const
00947       { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
00948 
00949     private:
00950       template<typename _Tp1>
00951         void
00952         _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const
00953         { _M_weak_this._M_assign(__p, __n); }
00954 
00955       template<typename _Tp1>
00956         friend void
00957         __enable_shared_from_this_helper(const __shared_count<_Lp>& __pn,
00958                      const __enable_shared_from_this* __pe,
00959                      const _Tp1* __px)
00960         {
00961       if (__pe != 0)
00962         __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
00963     }
00964 
00965       mutable __weak_ptr<_Tp, _Lp>  _M_weak_this;
00966     };
00967 
00968 
00969   // The actual TR1 shared_ptr, with forwarding constructors and
00970   // assignment operators.
00971   template<typename _Tp>
00972     class shared_ptr
00973     : public __shared_ptr<_Tp>
00974     {
00975     public:
00976       shared_ptr()
00977       : __shared_ptr<_Tp>() { }
00978 
00979       template<typename _Tp1>
00980         explicit
00981         shared_ptr(_Tp1* __p)
00982     : __shared_ptr<_Tp>(__p) { }
00983 
00984       template<typename _Tp1, typename _Deleter>
00985         shared_ptr(_Tp1* __p, _Deleter __d)
00986     : __shared_ptr<_Tp>(__p, __d) { }
00987 
00988       template<typename _Tp1>
00989         shared_ptr(const shared_ptr<_Tp1>& __r)
00990     : __shared_ptr<_Tp>(__r) { }
00991 
00992       template<typename _Tp1>
00993         explicit
00994         shared_ptr(const weak_ptr<_Tp1>& __r)
00995     : __shared_ptr<_Tp>(__r) { }
00996 
00997       template<typename _Tp1>
00998         explicit
00999         shared_ptr(std::auto_ptr<_Tp1>& __r)
01000     : __shared_ptr<_Tp>(__r) { }
01001 
01002       template<typename _Tp1>
01003         shared_ptr(const shared_ptr<_Tp1>& __r, __static_cast_tag)
01004     : __shared_ptr<_Tp>(__r, __static_cast_tag()) { }
01005 
01006       template<typename _Tp1>
01007         shared_ptr(const shared_ptr<_Tp1>& __r, __const_cast_tag)
01008     : __shared_ptr<_Tp>(__r, __const_cast_tag()) { }
01009 
01010       template<typename _Tp1>
01011         shared_ptr(const shared_ptr<_Tp1>& __r, __dynamic_cast_tag)
01012     : __shared_ptr<_Tp>(__r, __dynamic_cast_tag()) { }
01013 
01014       template<typename _Tp1>
01015         shared_ptr&
01016         operator=(const shared_ptr<_Tp1>& __r) // never throws
01017         {
01018       this->__shared_ptr<_Tp>::operator=(__r);
01019       return *this;
01020     }
01021 
01022       template<typename _Tp1>
01023         shared_ptr&
01024         operator=(std::auto_ptr<_Tp1>& __r)
01025         {
01026       this->__shared_ptr<_Tp>::operator=(__r);
01027       return *this;
01028     }
01029     };
01030 
01031   template<typename _Tp, typename _Tp1>
01032     shared_ptr<_Tp>
01033     static_pointer_cast(const shared_ptr<_Tp1>& __r)
01034     { return shared_ptr<_Tp>(__r, __static_cast_tag()); }
01035 
01036   template<typename _Tp, typename _Tp1>
01037     shared_ptr<_Tp>
01038     const_pointer_cast(const shared_ptr<_Tp1>& __r)
01039     { return shared_ptr<_Tp>(__r, __const_cast_tag()); }
01040 
01041   template<typename _Tp, typename _Tp1>
01042     shared_ptr<_Tp>
01043     dynamic_pointer_cast(const shared_ptr<_Tp1>& __r)
01044     { return shared_ptr<_Tp>(__r, __dynamic_cast_tag()); }
01045 
01046 
01047   // The actual TR1 weak_ptr, with forwarding constructors and
01048   // assignment operators.
01049   template<typename _Tp>
01050     class weak_ptr
01051     : public __weak_ptr<_Tp>
01052     {
01053     public:
01054       weak_ptr()
01055       : __weak_ptr<_Tp>() { }
01056       
01057       template<typename _Tp1>
01058         weak_ptr(const weak_ptr<_Tp1>& __r)
01059     : __weak_ptr<_Tp>(__r) { }
01060 
01061       template<typename _Tp1>
01062         weak_ptr(const shared_ptr<_Tp1>& __r)
01063     : __weak_ptr<_Tp>(__r) { }
01064 
01065       template<typename _Tp1>
01066         weak_ptr&
01067         operator=(const weak_ptr<_Tp1>& __r) // never throws
01068         {
01069       this->__weak_ptr<_Tp>::operator=(__r);
01070       return *this;
01071     }
01072 
01073       template<typename _Tp1>
01074         weak_ptr&
01075         operator=(const shared_ptr<_Tp1>& __r) // never throws
01076         {
01077       this->__weak_ptr<_Tp>::operator=(__r);
01078       return *this;
01079     }
01080 
01081       shared_ptr<_Tp>
01082       lock() const // never throws
01083       {
01084 #ifdef __GTHREADS
01085     if (this->expired())
01086       return shared_ptr<_Tp>();
01087 
01088     try
01089       {
01090         return shared_ptr<_Tp>(*this);
01091       }
01092     catch(const bad_weak_ptr&)
01093       {
01094         return shared_ptr<_Tp>();
01095       }
01096 #else
01097     return this->expired() ? shared_ptr<_Tp>()
01098                            : shared_ptr<_Tp>(*this);
01099 #endif
01100       }
01101     };
01102 
01103 
01104   template<typename _Tp>
01105     class enable_shared_from_this
01106     {
01107     protected:
01108       enable_shared_from_this() { }
01109       
01110       enable_shared_from_this(const enable_shared_from_this&) { }
01111 
01112       enable_shared_from_this&
01113       operator=(const enable_shared_from_this&)
01114       { return *this; }
01115 
01116       ~enable_shared_from_this() { }
01117 
01118     public:
01119       shared_ptr<_Tp>
01120       shared_from_this()
01121       { return shared_ptr<_Tp>(this->_M_weak_this); }
01122 
01123       shared_ptr<const _Tp>
01124       shared_from_this() const
01125       { return shared_ptr<const _Tp>(this->_M_weak_this); }
01126 
01127     private:
01128       template<typename _Tp1>
01129         void
01130         _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const
01131         { _M_weak_this._M_assign(__p, __n); }
01132 
01133       template<typename _Tp1>
01134         friend void
01135         __enable_shared_from_this_helper(const __shared_count<>& __pn,
01136                      const enable_shared_from_this* __pe,
01137                      const _Tp1* __px)
01138         {
01139       if (__pe != 0)
01140         __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
01141     }
01142 
01143       mutable weak_ptr<_Tp>  _M_weak_this;
01144     };
01145 
01146 _GLIBCXX_END_NAMESPACE
01147 } // namespace std
01148 
01149 #endif

Generated on Thu Nov 1 13:11:22 2007 for libstdc++ by  doxygen 1.5.1