boost_shared_ptr.h

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

Generated on Wed Mar 26 00:42:55 2008 for libstdc++ by  doxygen 1.5.1