当前位置: 代码迷 >> 综合 >> shared_ptr 源码分析
  详细解决方案

shared_ptr 源码分析

热度:4   发布时间:2023-12-22 02:43:20.0
  1. 共享指针

    • 说明

      • shared_ptr类提供类的行为接口.

      • 有专门的父类提供数据管理接口.

    • 实现

      • 涉及到继承,以及引用计数是否需要多线程安全.

      • 控制块的类型.

  2. 源码

    • shared_ptr

       template<typename _Tp>class shared_ptr : public __shared_ptr<_Tp>{
                template<typename... _Args>using _Constructible = typename enable_if<is_constructible<__shared_ptr<_Tp>, _Args...>::value>::type;template<typename _Arg>using _Assignable = typename enable_if<is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&>::type;public:using element_type = typename __shared_ptr<_Tp>::element_type;#if __cplusplus > 201402L
      # define __cpp_lib_shared_ptr_weak_type 201606using weak_type = weak_ptr<_Tp>;
      #endif/*** @brief Construct an empty %shared_ptr.* @post use_count()==0 && get()==0*/constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() {
                 }shared_ptr(const shared_ptr&) noexcept = default;/*** @brief Construct a %shared_ptr that owns the pointer @a __p.* @param __p A pointer that is convertible to element_type*.* @post use_count() == 1 && get() == __p* @throw std::bad_alloc, in which case @c delete @a __p is called.*/template<typename _Yp, typename = _Constructible<_Yp*>>explicitshared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) {
                 }/*** @brief Construct a %shared_ptr that owns the pointer @a __p* and the deleter @a __d.* @param __p A pointer.* @param __d A deleter.* @post use_count() == 1 && get() == __p* @throw std::bad_alloc, in which case @a __d(__p) is called.** Requirements: _Deleter's copy constructor and destructor must* not throw** __shared_ptr will release __p by calling __d(__p)*/template<typename _Yp, typename _Deleter,typename = _Constructible<_Yp*, _Deleter>>shared_ptr(_Yp* __p, _Deleter __d): __shared_ptr<_Tp>(__p, std::move(__d)) {
                 }/*** @brief Construct a %shared_ptr that owns a null pointer* and the deleter @a __d.* @param __p A null pointer constant.* @param __d A deleter.* @post use_count() == 1 && get() == __p* @throw std::bad_alloc, in which case @a __d(__p) is called.** Requirements: _Deleter's copy constructor and destructor must* not throw** The last owner will call __d(__p)*/template<typename _Deleter>shared_ptr(nullptr_t __p, _Deleter __d): __shared_ptr<_Tp>(__p, std::move(__d)) {
                 }/*** @brief Construct a %shared_ptr that owns the pointer @a __p* and the deleter @a __d.* @param __p A pointer.* @param __d A deleter.* @param __a An allocator.* @post use_count() == 1 && get() == __p* @throw std::bad_alloc, in which case @a __d(__p) is called.** Requirements: _Deleter's copy constructor and destructor must* not throw _Alloc's copy constructor and destructor must not* throw.** __shared_ptr will release __p by calling __d(__p)*/template<typename _Yp, typename _Deleter, typename _Alloc,typename = _Constructible<_Yp*, _Deleter, _Alloc>>shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a): __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) {
                 }/*** @brief Construct a %shared_ptr that owns a null pointer* and the deleter @a __d.* @param __p A null pointer constant.* @param __d A deleter.* @param __a An allocator.* @post use_count() == 1 && get() == __p* @throw std::bad_alloc, in which case @a __d(__p) is called.** Requirements: _Deleter's copy constructor and destructor must* not throw _Alloc's copy constructor and destructor must not* throw.** The last owner will call __d(__p)*/template<typename _Deleter, typename _Alloc>shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a): __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) {
                 }// Aliasing constructor/*** @brief Constructs a %shared_ptr instance that stores @a __p* and shares ownership with @a __r.* @param __r A %shared_ptr.* @param __p A pointer that will remain valid while @a *__r is valid.* @post get() == __p && use_count() == __r.use_count()** This can be used to construct a @c shared_ptr to a sub-object* of an object managed by an existing @c shared_ptr.** @code* shared_ptr< pair<int,int> > pii(new pair<int,int>());* shared_ptr<int> pi(pii, &pii->first);* assert(pii.use_count() == 2);* @endcode*/template<typename _Yp>shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept: __shared_ptr<_Tp>(__r, __p) {
                 }/*** @brief If @a __r is empty, constructs an empty %shared_ptr;* otherwise construct a %shared_ptr that shares ownership* with @a __r.* @param __r A %shared_ptr.* @post get() == __r.get() && use_count() == __r.use_count()*/template<typename _Yp,typename = _Constructible<const shared_ptr<_Yp>&>>shared_ptr(const shared_ptr<_Yp>& __r) noexcept: __shared_ptr<_Tp>(__r) {
                 }/*** @brief Move-constructs a %shared_ptr instance from @a __r.* @param __r A %shared_ptr rvalue.* @post *this contains the old value of @a __r, @a __r is empty.*/shared_ptr(shared_ptr&& __r) noexcept: __shared_ptr<_Tp>(std::move(__r)) {
                 }/*** @brief Move-constructs a %shared_ptr instance from @a __r.* @param __r A %shared_ptr rvalue.* @post *this contains the old value of @a __r, @a __r is empty.*/template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>shared_ptr(shared_ptr<_Yp>&& __r) noexcept: __shared_ptr<_Tp>(std::move(__r)) {
                 }/*** @brief Constructs a %shared_ptr that shares ownership with @a __r* and stores a copy of the pointer stored in @a __r.* @param __r A weak_ptr.* @post use_count() == __r.use_count()* @throw bad_weak_ptr when __r.expired(),* in which case the constructor has no effect.*/template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>explicit shared_ptr(const weak_ptr<_Yp>& __r): __shared_ptr<_Tp>(__r) {
                 }#if _GLIBCXX_USE_DEPRECATED
      #pragma GCC diagnostic push
      #pragma GCC diagnostic ignored "-Wdeprecated-declarations"template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>shared_ptr(auto_ptr<_Yp>&& __r);
      #pragma GCC diagnostic pop
      #endif// _GLIBCXX_RESOLVE_LIB_DEFECTS// 2399. shared_ptr's constructor from unique_ptr should be constrainedtemplate<typename _Yp, typename _Del,typename = _Constructible<unique_ptr<_Yp, _Del>>>shared_ptr(unique_ptr<_Yp, _Del>&& __r): __shared_ptr<_Tp>(std::move(__r)) {
                 }#if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED// This non-standard constructor exists to support conversions that// were possible in C++11 and C++14 but are ill-formed in C++17.// If an exception is thrown this constructor has no effect.template<typename _Yp, typename _Del,_Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0>shared_ptr(unique_ptr<_Yp, _Del>&& __r): __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) {
                 }
      #endif/*** @brief Construct an empty %shared_ptr.* @post use_count() == 0 && get() == nullptr*/constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() {
                 }shared_ptr& operator=(const shared_ptr&) noexcept = default;template<typename _Yp>_Assignable<const shared_ptr<_Yp>&>operator=(const shared_ptr<_Yp>& __r) noexcept{
                this->__shared_ptr<_Tp>::operator=(__r);return *this;}#if _GLIBCXX_USE_DEPRECATED
      #pragma GCC diagnostic push
      #pragma GCC diagnostic ignored "-Wdeprecated-declarations"template<typename _Yp>_Assignable<auto_ptr<_Yp>>operator=(auto_ptr<_Yp>&& __r){
                this->__shared_ptr<_Tp>::operator=(std::move(__r));return *this;}
      #pragma GCC diagnostic pop
      #endifshared_ptr&operator=(shared_ptr&& __r) noexcept{
                this->__shared_ptr<_Tp>::operator=(std::move(__r));return *this;}template<class _Yp>_Assignable<shared_ptr<_Yp>>operator=(shared_ptr<_Yp>&& __r) noexcept{
                this->__shared_ptr<_Tp>::operator=(std::move(__r));return *this;}template<typename _Yp, typename _Del>_Assignable<unique_ptr<_Yp, _Del>>operator=(unique_ptr<_Yp, _Del>&& __r){
                this->__shared_ptr<_Tp>::operator=(std::move(__r));return *this;}private:// This constructor is non-standard, it is used by allocate_shared.template<typename _Alloc, typename... _Args>shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,_Args&&... __args): __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...){
                 }template<typename _Yp, typename _Alloc, typename... _Args>friend shared_ptr<_Yp>allocate_shared(const _Alloc& __a, _Args&&... __args);// This constructor is non-standard, it is used by weak_ptr::lock().shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t): __shared_ptr<_Tp>(__r, std::nothrow) {
                 }friend class weak_ptr<_Tp>;};
      • 可以看到父类__shared_ptr,shared_ptr没有提供任何成员变量.

    • 说明

      • 提供的都是一些数据操作函数.

  3. 数据类

    • 源码

       template<typename _Tp, _Lock_policy _Lp>class __shared_ptr: public __shared_ptr_access<_Tp, _Lp>{
                public:using element_type = typename remove_extent<_Tp>::type;private:// Constraint for taking ownership of a pointer of type _Yp*:template<typename _Yp>using _SafeConv= typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;// Constraint for construction from shared_ptr and weak_ptr:template<typename _Yp, typename _Res = void>using _Compatible = typenameenable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;// Constraint for assignment from shared_ptr and weak_ptr:template<typename _Yp>using _Assignable = _Compatible<_Yp, __shared_ptr&>;// Constraint for construction from unique_ptr:template<typename _Yp, typename _Del, typename _Res = void,typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>using _UniqCompatible = typename enable_if<__and_<__sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*>>::value, _Res>::type;// Constraint for assignment from unique_ptr:template<typename _Yp, typename _Del>using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;public:#if __cplusplus > 201402Lusing weak_type = __weak_ptr<_Tp, _Lp>;
      #endifconstexpr __shared_ptr() noexcept: _M_ptr(0), _M_refcount(){
                 }template<typename _Yp, typename = _SafeConv<_Yp>>explicit__shared_ptr(_Yp* __p): _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type()){
                static_assert( !is_void<_Yp>::value, "incomplete type" );static_assert( sizeof(_Yp) > 0, "incomplete type" );_M_enable_shared_from_this_with(__p);}template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>__shared_ptr(_Yp* __p, _Deleter __d): _M_ptr(__p), _M_refcount(__p, std::move(__d)){
                static_assert(__is_invocable<_Deleter&, _Yp*&>::value,"deleter expression d(p) is well-formed");_M_enable_shared_from_this_with(__p);}template<typename _Yp, typename _Deleter, typename _Alloc,typename = _SafeConv<_Yp>>__shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a): _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a)){
                static_assert(__is_invocable<_Deleter&, _Yp*&>::value,"deleter expression d(p) is well-formed");_M_enable_shared_from_this_with(__p);}template<typename _Deleter>__shared_ptr(nullptr_t __p, _Deleter __d): _M_ptr(0), _M_refcount(__p, std::move(__d)){
                 }template<typename _Deleter, typename _Alloc>__shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a): _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a)){
                 }template<typename _Yp>__shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,element_type* __p) noexcept: _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws{
                 }__shared_ptr(const __shared_ptr&) noexcept = default;__shared_ptr& operator=(const __shared_ptr&) noexcept = default;~__shared_ptr() = default;template<typename _Yp, typename = _Compatible<_Yp>>__shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount){
                 }__shared_ptr(__shared_ptr&& __r) noexcept: _M_ptr(__r._M_ptr), _M_refcount(){
                _M_refcount._M_swap(__r._M_refcount);__r._M_ptr = 0;}template<typename _Yp, typename = _Compatible<_Yp>>__shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept: _M_ptr(__r._M_ptr), _M_refcount(){
                _M_refcount._M_swap(__r._M_refcount);__r._M_ptr = 0;}template<typename _Yp, typename = _Compatible<_Yp>>explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r): _M_refcount(__r._M_refcount) // may throw{
                // It is now safe to copy __r._M_ptr, as// _M_refcount(__r._M_refcount) did not throw._M_ptr = __r._M_ptr;}// If an exception is thrown this constructor has no effect.template<typename _Yp, typename _Del,typename = _UniqCompatible<_Yp, _Del>>__shared_ptr(unique_ptr<_Yp, _Del>&& __r): _M_ptr(__r.get()), _M_refcount(){
                auto __raw = __to_address(__r.get());_M_refcount = __shared_count<_Lp>(std::move(__r));_M_enable_shared_from_this_with(__raw);}#if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATEDprotected:// If an exception is thrown this constructor has no effect.template<typename _Tp1, typename _Del,typename enable_if<__and_<__not_<is_array<_Tp>>, is_array<_Tp1>,is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*>>::value, bool>::type = true>__shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete): _M_ptr(__r.get()), _M_refcount(){
                auto __raw = __to_address(__r.get());_M_refcount = __shared_count<_Lp>(std::move(__r));_M_enable_shared_from_this_with(__raw);}public:
      #endif#if _GLIBCXX_USE_DEPRECATED
      #pragma GCC diagnostic push
      #pragma GCC diagnostic ignored "-Wdeprecated-declarations"// Postcondition: use_count() == 1 and __r.get() == 0template<typename _Yp, typename = _Compatible<_Yp>>__shared_ptr(auto_ptr<_Yp>&& __r);
      #pragma GCC diagnostic pop
      #endifconstexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() {
                 }template<typename _Yp>_Assignable<_Yp>operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept{
                _M_ptr = __r._M_ptr;_M_refcount = __r._M_refcount; // __shared_count::op= doesn't throwreturn *this;}#if _GLIBCXX_USE_DEPRECATED
      #pragma GCC diagnostic push
      #pragma GCC diagnostic ignored "-Wdeprecated-declarations"template<typename _Yp>_Assignable<_Yp>operator=(auto_ptr<_Yp>&& __r){
                __shared_ptr(std::move(__r)).swap(*this);return *this;}
      #pragma GCC diagnostic pop
      #endif__shared_ptr&operator=(__shared_ptr&& __r) noexcept{
                __shared_ptr(std::move(__r)).swap(*this);return *this;}template<class _Yp>_Assignable<_Yp>operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept{
                __shared_ptr(std::move(__r)).swap(*this);return *this;}template<typename _Yp, typename _Del>_UniqAssignable<_Yp, _Del>operator=(unique_ptr<_Yp, _Del>&& __r){
                __shared_ptr(std::move(__r)).swap(*this);return *this;}voidreset() noexcept{
                 __shared_ptr().swap(*this); }template<typename _Yp>_SafeConv<_Yp>reset(_Yp* __p) // _Yp must be complete.{
                // Catch self-reset errors.__glibcxx_assert(__p == 0 || __p != _M_ptr);__shared_ptr(__p).swap(*this);}template<typename _Yp, typename _Deleter>_SafeConv<_Yp>reset(_Yp* __p, _Deleter __d){
                 __shared_ptr(__p, std::move(__d)).swap(*this); }template<typename _Yp, typename _Deleter, typename _Alloc>_SafeConv<_Yp>reset(_Yp* __p, _Deleter __d, _Alloc __a){
                 __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); }element_type*get() const noexcept{
                 return _M_ptr; }explicit operator bool() const // never throws{
                 return _M_ptr == 0 ? false : true; }boolunique() const noexcept{
                 return _M_refcount._M_unique(); }longuse_count() const noexcept{
                 return _M_refcount._M_get_use_count(); }voidswap(__shared_ptr<_Tp, _Lp>& __other) noexcept{
                std::swap(_M_ptr, __other._M_ptr);_M_refcount._M_swap(__other._M_refcount);}template<typename _Tp1>boolowner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept{
                 return _M_refcount._M_less(__rhs._M_refcount); }template<typename _Tp1>boolowner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept{
                 return _M_refcount._M_less(__rhs._M_refcount); }protected:// This constructor is non-standard, it is used by allocate_shared.template<typename _Alloc, typename... _Args>__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,_Args&&... __args): _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,std::forward<_Args>(__args)...){
                // _M_ptr needs to point to the newly constructed object.// This relies on _Sp_counted_ptr_inplace::_M_get_deleter.
      #if __cpp_rttivoid* __p = _M_refcount._M_get_deleter(typeid(__tag));
      #elsevoid* __p = _M_refcount._M_get_deleter(_Sp_make_shared_tag::_S_ti());
      #endif_M_ptr = static_cast<_Tp*>(__p);_M_enable_shared_from_this_with(_M_ptr);}template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,typename... _Args>friend __shared_ptr<_Tp1, _Lp1>__allocate_shared(const _Alloc& __a, _Args&&... __args);// This constructor is used by __weak_ptr::lock() and// shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).__shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t): _M_refcount(__r._M_refcount, std::nothrow){
                _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;}friend class __weak_ptr<_Tp, _Lp>;private:template<typename _Yp>using __esft_base_t = decltype(__enable_shared_from_this_base(std::declval<const __shared_count<_Lp>&>(),std::declval<_Yp*>()));// Detect an accessible and unambiguous enable_shared_from_this base.template<typename _Yp, typename = void>struct __has_esft_base: false_type {
                 };template<typename _Yp>struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>: __not_<is_array<_Tp>> {
                 }; // No enable shared_from_this for arraystemplate<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>typename enable_if<__has_esft_base<_Yp2>::value>::type_M_enable_shared_from_this_with(_Yp* __p) noexcept{
                if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))__base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);}template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>typename enable_if<!__has_esft_base<_Yp2>::value>::type_M_enable_shared_from_this_with(_Yp*) noexcept{
                 }void*_M_get_deleter(const std::type_info& __ti) const noexcept{
                 return _M_refcount._M_get_deleter(__ti); }template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;template<typename _Del, typename _Tp1, _Lock_policy _Lp1>friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;template<typename _Del, typename _Tp1>friend _Del* get_deleter(const shared_ptr<_Tp1>&) noexcept;element_type*    _M_ptr;         // Contained pointer.__shared_count<_Lp>  _M_refcount;    // Reference counter.};
      • _Tp是数据类型._Lp是互斥机制.

      • _Lp决定了是否多线程安全.

    • 数据

      • 一个数据指针和引用计数__shared_count<_Lp>.

      • 通过构造可以看到,数据指针也会传入数据指针.

    • _Lock_policy

      enum _Lock_policy {
                 _S_single, _S_mutex, _S_atomic }; 
      
      • 可以看到是枚举类型.

  4. 引用计数管理__shared_count

    • 说明

      • 作用就是引用计数.
    • 源码

       template<_Lock_policy _Lp>class __shared_count{
                public:constexpr __shared_count() noexcept : _M_pi(0){
                 }template<typename _Ptr>explicit__shared_count(_Ptr __p) : _M_pi(0){
                __try{
                _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);}__catch(...){
                delete __p;__throw_exception_again;}}template<typename _Ptr>__shared_count(_Ptr __p, /* is_array = */ false_type): __shared_count(__p){
                 }template<typename _Ptr>__shared_count(_Ptr __p, /* is_array = */ true_type): __shared_count(__p, __sp_array_delete{
                }, allocator<void>()){
                 }template<typename _Ptr, typename _Deleter>__shared_count(_Ptr __p, _Deleter __d): __shared_count(__p, std::move(__d), allocator<void>()){
                 }template<typename _Ptr, typename _Deleter, typename _Alloc>__shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0){
                typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;__try{
                typename _Sp_cd_type::__allocator_type __a2(__a);auto __guard = std::__allocate_guarded(__a2);_Sp_cd_type* __mem = __guard.get();::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));_M_pi = __mem;__guard = nullptr;}__catch(...){
                __d(__p); // Call _Deleter on __p.__throw_exception_again;}}template<typename _Tp, typename _Alloc, typename... _Args>__shared_count(_Sp_make_shared_tag, _Tp*, const _Alloc& __a,_Args&&... __args): _M_pi(0){
                typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;typename _Sp_cp_type::__allocator_type __a2(__a);auto __guard = std::__allocate_guarded(__a2);_Sp_cp_type* __mem = __guard.get();::new (__mem) _Sp_cp_type(std::move(__a),std::forward<_Args>(__args)...);_M_pi = __mem;__guard = nullptr;}#if _GLIBCXX_USE_DEPRECATED
      #pragma GCC diagnostic push
      #pragma GCC diagnostic ignored "-Wdeprecated-declarations"// Special case for auto_ptr<_Tp> to provide the strong guarantee.template<typename _Tp>explicit__shared_count(std::auto_ptr<_Tp>&& __r);
      #pragma GCC diagnostic pop
      #endif// Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.template<typename _Tp, typename _Del>explicit__shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0){
                // _GLIBCXX_RESOLVE_LIB_DEFECTS// 2415. Inconsistency between unique_ptr and shared_ptrif (__r.get() == nullptr)return;using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;using _Del2 = typename conditional<is_reference<_Del>::value,reference_wrapper<typename remove_reference<_Del>::type>,_Del>::type;using _Sp_cd_type= _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;using _Alloc = allocator<_Sp_cd_type>;using _Alloc_traits = allocator_traits<_Alloc>;_Alloc __a;_Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);_Alloc_traits::construct(__a, __mem, __r.release(),__r.get_deleter());  // non-throwing_M_pi = __mem;}// Throw bad_weak_ptr when __r._M_get_use_count() == 0.explicit __shared_count(const __weak_count<_Lp>& __r);// Does not throw if __r._M_get_use_count() == 0, caller must check.explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);~__shared_count() noexcept{
                if (_M_pi != nullptr)_M_pi->_M_release();}__shared_count(const __shared_count& __r) noexcept: _M_pi(__r._M_pi){
                if (_M_pi != 0)_M_pi->_M_add_ref_copy();}__shared_count&operator=(const __shared_count& __r) noexcept{
                _Sp_counted_base<_Lp>* __tmp = __r._M_pi;if (__tmp != _M_pi){
                if (__tmp != 0)__tmp->_M_add_ref_copy();if (_M_pi != 0)_M_pi->_M_release();_M_pi = __tmp;}return *this;}void_M_swap(__shared_count& __r) noexcept{
                _Sp_counted_base<_Lp>* __tmp = __r._M_pi;__r._M_pi = _M_pi;_M_pi = __tmp;}long_M_get_use_count() const noexcept{
                 return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }bool_M_unique() const noexcept{
                 return this->_M_get_use_count() == 1; }void*_M_get_deleter(const std::type_info& __ti) const noexcept{
                 return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }bool_M_less(const __shared_count& __rhs) const noexcept{
                 return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }bool_M_less(const __weak_count<_Lp>& __rhs) const noexcept{
                 return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }// Friend function injected into enclosing namespace and found by ADLfriend inline booloperator==(const __shared_count& __a, const __shared_count& __b) noexcept{
                 return __a._M_pi == __b._M_pi; }private:friend class __weak_count<_Lp>;_Sp_counted_base<_Lp>*  _M_pi;};
      • 可以看到是一个指针类型,指针类型指向的是一个多肽类.

      • 有好几种子类. 分别对应默认析构类型,自定义析构类型,make_shared类型.

    • 说明

      • 仅仅一个指针.

      • 其他的则是引用计数的操作.

    • 须知

      • 析构函数会负责数据的析构和引用计数的管理.

    • _Sp_counted_base的多态

      • 根据构造时的入参不同选用不同的计数器.

      • 原始指针,默认析构.

           template<typename _Ptr>explicit__shared_count(_Ptr __p) : _M_pi(0){
                __try{
                _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);}__catch(...){
                delete __p;__throw_exception_again;}}
      
      • 自定义析构,使用的_Sp_counted_ptr;

           template<typename _Ptr, typename _Deleter>__shared_count(_Ptr __p, _Deleter __d): __shared_count(__p, std::move(__d), allocator<void>()){
                 }template<typename _Ptr, typename _Deleter, typename _Alloc>__shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0){
                typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;__try{
                typename _Sp_cd_type::__allocator_type __a2(__a);auto __guard = std::__allocate_guarded(__a2);_Sp_cd_type* __mem = __guard.get();::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));_M_pi = __mem;__guard = nullptr;}__catch(...){
                __d(__p); // Call _Deleter on __p.__throw_exception_again;}}
      • 析构函数,使用的是_Sp_counted_deleter.

           template<typename _Tp, typename _Alloc, typename... _Args>__shared_count(_Sp_make_shared_tag, _Tp*, const _Alloc& __a,_Args&&... __args): _M_pi(0){
                typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;typename _Sp_cp_type::__allocator_type __a2(__a);auto __guard = std::__allocate_guarded(__a2);_Sp_cp_type* __mem = __guard.get();::new (__mem) _Sp_cp_type(std::move(__a),std::forward<_Args>(__args)...);_M_pi = __mem;__guard = nullptr;}
      • make_shared创建的使用的是_Sp_counted_ptr_inplace.

  5. 计数数据的实现基类

    • 代码

       template<_Lock_policy _Lp = __default_lock_policy>class _Sp_counted_base: public _Mutex_base<_Lp>{
                public:_Sp_counted_base() noexcept: _M_use_count(1), _M_weak_count(1) {
                 }virtual~_Sp_counted_base() noexcept{
                 }// Called when _M_use_count drops to zero, to release the resources// managed by *this.virtual void_M_dispose() noexcept = 0;// Called when _M_weak_count drops to zero.virtual void_M_destroy() noexcept{
                 delete this; }virtual void*_M_get_deleter(const std::type_info&) noexcept = 0;void_M_add_ref_copy(){
                 __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }void_M_add_ref_lock();bool_M_add_ref_lock_nothrow();void_M_release() noexcept{
                // Be race-detector-friendly. For more info see bits/c++config._GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1){
                _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);_M_dispose();// There must be a memory barrier between dispose() and destroy()// to ensure that the effects of dispose() are observed in the// thread that runs destroy().// See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.htmlif (_Mutex_base<_Lp>::_S_need_barriers){
                __atomic_thread_fence (__ATOMIC_ACQ_REL);}// Be race-detector-friendly. For more info see bits/c++config._GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,-1) == 1){
                _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);_M_destroy();}}}void_M_weak_add_ref() noexcept{
                 __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }void_M_weak_release() noexcept{
                // Be race-detector-friendly. For more info see bits/c++config._GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1){
                _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);if (_Mutex_base<_Lp>::_S_need_barriers){
                // See _M_release(),// destroy() must observe results of dispose()__atomic_thread_fence (__ATOMIC_ACQ_REL);}_M_destroy();}}long_M_get_use_count() const noexcept{
                // No memory barrier is used here so there is no synchronization// with other threads.return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED);}private:_Sp_counted_base(_Sp_counted_base const&) = delete;_Sp_counted_base& operator=(_Sp_counted_base const&) = delete;_Atomic_word  _M_use_count;     // #shared_Atomic_word  _M_weak_count;    // #weak + (#shared != 0)};
    • 说明

      • 首先有两个数据,共享计数和弱引用计数.

      • 那么,怎么操作这个引用计数呢.

    • 成员函数的实现

       template<>inline void_Sp_counted_base<_S_single>::_M_add_ref_lock(){
                if (_M_use_count == 0)__throw_bad_weak_ptr();++_M_use_count;}template<>inline void_Sp_counted_base<_S_mutex>::_M_add_ref_lock(){
                __gnu_cxx::__scoped_lock sentry(*this);if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0){
                _M_use_count = 0;__throw_bad_weak_ptr();}}template<>inline void_Sp_counted_base<_S_atomic>::_M_add_ref_lock(){
                // Perform lock-free add-if-not-zero operation._Atomic_word __count = _M_get_use_count();do{
                if (__count == 0)__throw_bad_weak_ptr();// Replace the current counter value with the old value + 1, as// long as it's not changed meanwhile.}while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,true, __ATOMIC_ACQ_REL,__ATOMIC_RELAXED));}template<>inline bool_Sp_counted_base<_S_single>::_M_add_ref_lock_nothrow(){
                if (_M_use_count == 0)return false;++_M_use_count;return true;}template<>inline bool_Sp_counted_base<_S_mutex>::_M_add_ref_lock_nothrow(){
                __gnu_cxx::__scoped_lock sentry(*this);if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0){
                _M_use_count = 0;return false;}return true;}template<>inline bool_Sp_counted_base<_S_atomic>::_M_add_ref_lock_nothrow(){
                // Perform lock-free add-if-not-zero operation._Atomic_word __count = _M_get_use_count();do{
                if (__count == 0)return false;// Replace the current counter value with the old value + 1, as// long as it's not changed meanwhile.}while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,true, __ATOMIC_ACQ_REL,__ATOMIC_RELAXED));return true;}template<>inline void_Sp_counted_base<_S_single>::_M_add_ref_copy(){
                 ++_M_use_count; }template<>inline void_Sp_counted_base<_S_single>::_M_release() noexcept{
                if (--_M_use_count == 0){
                _M_dispose();if (--_M_weak_count == 0)_M_destroy();}}template<>inline void_Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept{
                 ++_M_weak_count; }template<>inline void_Sp_counted_base<_S_single>::_M_weak_release() noexcept{
                if (--_M_weak_count == 0)_M_destroy();}template<>inline long_Sp_counted_base<_S_single>::_M_get_use_count() const noexcept{
                 return _M_use_count; }
      • 根据各种特例化实现.

      • 可以实现多种多线程安全机制.

      • 枷锁,互斥,或者是单线程的++,--.

    • 父类

       // Empty helper class except when the template argument is _S_mutex.template<_Lock_policy _Lp>class _Mutex_base{
                protected:// The atomic policy uses fully-fenced builtins, single doesn't care.enum {
                 _S_need_barriers = 0 };};template<>class _Mutex_base<_S_mutex>: public __gnu_cxx::__mutex{
                protected:// This policy is used when atomic builtins are not available.// The replacement atomic operations might not have the necessary// memory barriers.enum {
                 _S_need_barriers = 1 };};
      
      • 可以看到mutexatomic版本.

      • 普通版不需要.

  6. 计数数据的实现: 多态子类

    • 说明

      • 主要是用来适配不同的析构.

    • 默认

       template<typename _Ptr, _Lock_policy _Lp>class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>{
                public:explicit_Sp_counted_ptr(_Ptr __p) noexcept: _M_ptr(__p) {
                 }virtual void_M_dispose() noexcept{
                 delete _M_ptr; }virtual void_M_destroy() noexcept{
                 delete this; }virtual void*_M_get_deleter(const std::type_info&) noexcept{
                 return nullptr; }_Sp_counted_ptr(const _Sp_counted_ptr&) = delete;_Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;private:_Ptr             _M_ptr;};
      
      • 实现了虚函数析构器和释放自己的方式.

      • 默认都是delete.

    • 自定义析构

       // Support for custom deleter and/or allocatortemplate<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>{
                class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>{
                typedef _Sp_ebo_helper<0, _Deleter> _Del_base;typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;public:_Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept: _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a){
                 }_Deleter& _M_del() noexcept {
                 return _Del_base::_S_get(*this); }_Alloc& _M_alloc() noexcept {
                 return _Alloc_base::_S_get(*this); }_Ptr _M_ptr;};public:using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;// __d(__p) must not throw._Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept: _M_impl(__p, std::move(__d), _Alloc()) {
                 }// __d(__p) must not throw._Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept: _M_impl(__p, std::move(__d), __a) {
                 }~_Sp_counted_deleter() noexcept {
                 }virtual void_M_dispose() noexcept{
                 _M_impl._M_del()(_M_impl._M_ptr); }virtual void_M_destroy() noexcept{
                __allocator_type __a(_M_impl._M_alloc());__allocated_ptr<__allocator_type> __guard_ptr{
                 __a, this };this->~_Sp_counted_deleter();}virtual void*_M_get_deleter(const std::type_info& __ti) noexcept{
                
      #if __cpp_rtti// _GLIBCXX_RESOLVE_LIB_DEFECTS// 2400. shared_ptr's get_deleter() should use addressof()return __ti == typeid(_Deleter)? std::__addressof(_M_impl._M_del()): nullptr;
      #elsereturn nullptr;
      #endif}private:_Impl _M_impl;};
      • 可以看到,实现的虚函数,数据析构和自我析构的实现不一样.

      • 自定义析构函数析构.

    • make_shared

       template<typename _Tp, typename _Alloc, _Lock_policy _Lp>class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>{
                class _Impl : _Sp_ebo_helper<0, _Alloc>{
                typedef _Sp_ebo_helper<0, _Alloc> _A_base;public:explicit _Impl(_Alloc __a) noexcept : _A_base(__a) {
                 }_Alloc& _M_alloc() noexcept {
                 return _A_base::_S_get(*this); }__gnu_cxx::__aligned_buffer<_Tp> _M_storage;};public:using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;template<typename... _Args>_Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args): _M_impl(__a){
                // _GLIBCXX_RESOLVE_LIB_DEFECTS// 2070. allocate_shared should use allocator_traits<A>::constructallocator_traits<_Alloc>::construct(__a, _M_ptr(),std::forward<_Args>(__args)...); // might throw}~_Sp_counted_ptr_inplace() noexcept {
                 }virtual void_M_dispose() noexcept{
                allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());}// Override because the allocator needs to know the dynamic typevirtual void_M_destroy() noexcept{
                __allocator_type __a(_M_impl._M_alloc());__allocated_ptr<__allocator_type> __guard_ptr{
                 __a, this };this->~_Sp_counted_ptr_inplace();}// Sneaky trick so __shared_ptr can get the managed pointervirtual void*_M_get_deleter(const std::type_info& __ti) noexcept{
                
      #if __cpp_rttiif (__ti == typeid(_Sp_make_shared_tag))
      #elseif (&__ti == &_Sp_make_shared_tag::_S_ti())
      #endifreturn const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());return nullptr;}private:_Tp* _M_ptr() noexcept {
                 return _M_impl._M_storage._M_ptr(); }_Impl _M_impl;};
      • 可以看到,用的自定义构造器的析构器进行资源释放.

  7. 如何区分数组,原始指针,和数据为void类型

    • 源码

       template<typename _Tp, _Lock_policy _Lp,bool = is_array<_Tp>::value, bool = is_void<_Tp>::value>class __shared_ptr_access{
                public:using element_type = _Tp;element_type&operator*() const noexcept{
                __glibcxx_assert(_M_get() != nullptr);return *_M_get();}element_type*operator->() const noexcept{
                _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);return _M_get();}private:element_type*_M_get() const noexcept{
                 return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }};// Define operator-> for shared_ptr<cv void>.template<typename _Tp, _Lock_policy _Lp>class __shared_ptr_access<_Tp, _Lp, false, true>{
                public:using element_type = _Tp;element_type*operator->() const noexcept{
                auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get();_GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr);return __ptr;}};// Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>.template<typename _Tp, _Lock_policy _Lp>class __shared_ptr_access<_Tp, _Lp, true, false>{
                public:using element_type = typename remove_extent<_Tp>::type;#if __cplusplus <= 201402L[[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]]element_type&operator*() const noexcept{
                __glibcxx_assert(_M_get() != nullptr);return *_M_get();}[[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]]element_type*operator->() const noexcept{
                _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);return _M_get();}
      #endifelement_type&operator[](ptrdiff_t __i) const{
                __glibcxx_assert(_M_get() != nullptr);__glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);return _M_get()[__i];}private:element_type*_M_get() const noexcept{
                 return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }};
      • 根据特例化,实现了不同的父类.

    • 总结

      • 父类不同,子类支持的指针行为也不同.

  8. weak计数

    • 源码

       template<_Lock_policy _Lp>class __weak_count{
                public:constexpr __weak_count() noexcept : _M_pi(nullptr){
                 }__weak_count(const __shared_count<_Lp>& __r) noexcept: _M_pi(__r._M_pi){
                if (_M_pi != nullptr)_M_pi->_M_weak_add_ref();}__weak_count(const __weak_count& __r) noexcept: _M_pi(__r._M_pi){
                if (_M_pi != nullptr)_M_pi->_M_weak_add_ref();}__weak_count(__weak_count&& __r) noexcept: _M_pi(__r._M_pi){
                 __r._M_pi = nullptr; }~__weak_count() noexcept{
                if (_M_pi != nullptr)_M_pi->_M_weak_release();}__weak_count&operator=(const __shared_count<_Lp>& __r) noexcept{
                _Sp_counted_base<_Lp>* __tmp = __r._M_pi;if (__tmp != nullptr)__tmp->_M_weak_add_ref();if (_M_pi != nullptr)_M_pi->_M_weak_release();_M_pi = __tmp;return *this;}__weak_count&operator=(const __weak_count& __r) noexcept{
                _Sp_counted_base<_Lp>* __tmp = __r._M_pi;if (__tmp != nullptr)__tmp->_M_weak_add_ref();if (_M_pi != nullptr)_M_pi->_M_weak_release();_M_pi = __tmp;return *this;}__weak_count&operator=(__weak_count&& __r) noexcept{
                if (_M_pi != nullptr)_M_pi->_M_weak_release();_M_pi = __r._M_pi;__r._M_pi = nullptr;return *this;}void_M_swap(__weak_count& __r) noexcept{
                _Sp_counted_base<_Lp>* __tmp = __r._M_pi;__r._M_pi = _M_pi;_M_pi = __tmp;}long_M_get_use_count() const noexcept{
                 return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }bool_M_less(const __weak_count& __rhs) const noexcept{
                 return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }bool_M_less(const __shared_count<_Lp>& __rhs) const noexcept{
                 return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }// Friend function injected into enclosing namespace and found by ADLfriend inline booloperator==(const __weak_count& __a, const __weak_count& __b) noexcept{
                 return __a._M_pi == __b._M_pi; }private:friend class __shared_count<_Lp>;_Sp_counted_base<_Lp>*  _M_pi;};
    • 说明

      • 采用shared_count类似的手段,而且weak_countshared_count共享数据_Sp_counted_base<_Lp>* _M_pi;.

      • 可以根据构造和析构查看,释放和创建的行为.

      • 可以根据前面的_Sp_counted_base看到,weak的释放是释放整个计数对象.

  9. 计数

    • 引用计数

      • 可以看到__shared_countoperator=的拷贝构造.仅仅共享加一.

      • weak+1weak的计数上.

    • 析构

      • 只有shared0会释放.

      • 只有weak0的时候会释放计数对象.

  10. 总结

    • 指针操作由__shared_ptr_access的特例化决定.以区分数组,指针和void.

    • 元素的基本操作由shared_ptr的外层封装.

    • __shared_count__shared_ptr的成员变量

    • __weak_count__weak_ptr的成员变量

    • __weak_count__shared_count指向对象,但是分别控制_Sp_counted_base的两个计数成员.

    • 引用计数由_Sp_counted_base来控制.

    • 引用计数的多线程安全由_Sp_counted_base的成员函数特例化实现来控制.

    • 析构的不同对待由_Sp_counted_base的子类和虚函数重载类控制.