shared_ptr_base.h

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

Generated on 11 Jan 2010 for libstdc++ by  doxygen 1.6.1