tr1/shared_ptr.h

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

Generated on Thu Jul 23 21:16:16 2009 for libstdc++ by  doxygen 1.5.8