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

Generated on 17 Nov 2009 for libstdc++ by  doxygen 1.6.1