源码来自llvm 8.0.0的libc++,精简了一些不太重要的部分,重要的地方加了注释。目的是学习智能指针的实现原理。关于shared_ptr的线程安全问题,cppreference上的描述:
All member functions (including copy constructor and copy assignment) can be called by multiple threads on different instances of shared_ptr without additional synchronization even if these instances are copies and share ownership of the same object. If multiple threads of execution access the same shared_ptr without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur; the shared_ptr overloads of atomic functions can be used to prevent the data race.
templateclass _LIBCPP_TEMPLATE_VIS shared_ptr // 3740{public: typedef _Tp element_type;#if _LIBCPP_STD_VER > 14 typedef weak_ptr<_Tp> weak_type;#endifprivate: element_type* __ptr_; // 直接使用,提升性能 __shared_weak_count* __cntrl_; // 底层的引用计数 struct __nat {int __for_bool_;};public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR shared_ptr() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT; template explicit shared_ptr(_Yp* __p, typename enable_if <_Yp*, element_type*>::value, __nat>::type = __nat()); ~shared_ptr(); _LIBCPP_INLINE_VISIBILITY shared_ptr& operator=(const shared_ptr& __r) _NOEXCEPT; template typename enable_if < is_convertible<_Yp*, element_type*>::value, shared_ptr& >::type _LIBCPP_INLINE_VISIBILITY operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY shared_ptr& operator=(shared_ptr&& __r) _NOEXCEPT; template typename enable_if < is_convertible<_Yp*, element_type*>::value, shared_ptr<_Tp>& >::type _LIBCPP_INLINE_VISIBILITY operator=(shared_ptr<_Yp>&& __r); _LIBCPP_INLINE_VISIBILITY void swap(shared_ptr& __r) _NOEXCEPT; template typename enable_if < is_convertible<_Yp*, element_type*>::value, void >::type _LIBCPP_INLINE_VISIBILITY reset(_Yp* __p); _LIBCPP_INLINE_VISIBILITY element_type* get() const _NOEXCEPT {return __ptr_;} // 直接返回__ptr_,无需到__cntrl_里才返回指针 _LIBCPP_INLINE_VISIBILITY typename add_lvalue_reference ::type operator*() const _NOEXCEPT {return *__ptr_;} _LIBCPP_INLINE_VISIBILITY element_type* operator->() const _NOEXCEPT {return __ptr_;} _LIBCPP_INLINE_VISIBILITY long use_count() const _NOEXCEPT {return __cntrl_ ? __cntrl_->use_count() : 0;} _LIBCPP_INLINE_VISIBILITY bool unique() const _NOEXCEPT {return use_count() == 1;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return get() != 0;} template _LIBCPP_INLINE_VISIBILITY bool owner_before(shared_ptr<_Up> const& __p) const _NOEXCEPT {return __cntrl_ < __p.__cntrl_;} _LIBCPP_INLINE_VISIBILITY bool __owner_equivalent(const shared_ptr& __p) const {return __cntrl_ == __p.__cntrl_;} template static shared_ptr<_Tp> make_shared(_Args&& ...__args); template static shared_ptr<_Tp> allocate_shared(const _Alloc& __a, _Args&& ...__args); static shared_ptr<_Tp> make_shared(); template static shared_ptr<_Tp> make_shared(_A0&);private: template ::value> struct __shared_ptr_default_allocator { typedef allocator<_Yp> type; }; template struct __shared_ptr_default_allocator<_Yp, true> { typedef allocator<__shared_ptr_dummy_rebind_allocator_type> type; }; template _LIBCPP_INLINE_VISIBILITY typename enable_if <_OrigPtr*, const enable_shared_from_this<_Yp>* >::value, void>::type __enable_weak_this(const enable_shared_from_this<_Yp>* __e, _OrigPtr* __ptr) _NOEXCEPT { typedef typename remove_cv<_Yp>::type _RawYp; if (__e && __e->__weak_this_.expired()) { __e->__weak_this_ = shared_ptr<_RawYp>(*this, const_cast<_RawYp*>(static_cast (__ptr))); } } _LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {} template friend class _LIBCPP_TEMPLATE_VIS shared_ptr; template friend class _LIBCPP_TEMPLATE_VIS weak_ptr;};template inline_LIBCPP_CONSTEXPRshared_ptr<_Tp>::shared_ptr() _NOEXCEPT : __ptr_(0), __cntrl_(0){}template inline_LIBCPP_CONSTEXPRshared_ptr<_Tp>::shared_ptr(nullptr_t) _NOEXCEPT : __ptr_(0), __cntrl_(0){}template template shared_ptr<_Tp>::shared_ptr(_Yp* __p, typename enable_if <_Yp*, element_type*>::value, __nat>::type) : __ptr_(__p){ unique_ptr<_Yp> __hold(__p); typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, _AllocT > _CntrlBlk; __cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), _AllocT()); // 核心 __hold.release(); __enable_weak_this(__p, __p);}template inlineshared_ptr<_Tp>::shared_ptr(const shared_ptr& __r) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_){ if (__cntrl_) __cntrl_->__add_shared(); // 拷贝构造只是简单拷贝两个指针,再引用计数加1}template shared_ptr<_Tp>::~shared_ptr(){ if (__cntrl_) __cntrl_->__release_shared(); // __cntrl_中的引用计数减1,如果无其它引用,则执行释放}template inlinevoidshared_ptr<_Tp>::swap(shared_ptr& __r) _NOEXCEPT{ _VSTD::swap(__ptr_, __r.__ptr_); _VSTD::swap(__cntrl_, __r.__cntrl_);}template template inlinetypename enable_if< is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value, void>::typeshared_ptr<_Tp>::reset(_Yp* __p){ shared_ptr(__p).swap(*this);}template template inlinetypename enable_if< is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value, shared_ptr<_Tp>&>::typeshared_ptr<_Tp>::operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT{ shared_ptr(__r).swap(*this); // 赋值是先构造右值,再与本对象swap return *this;}template class __shared_ptr_pointer : public __shared_weak_count{ __compressed_pair<__compressed_pair<_Tp, _Dp>, _Alloc> __data_;public: _LIBCPP_INLINE_VISIBILITY __shared_ptr_pointer(_Tp __p, _Dp __d, _Alloc __a) : __data_(__compressed_pair<_Tp, _Dp>(__p, _VSTD::move(__d)), _VSTD::move(__a)) {}#ifndef _LIBCPP_NO_RTTI virtual const void* __get_deleter(const type_info&) const _NOEXCEPT;#endifprivate: virtual void __on_zero_shared() _NOEXCEPT; virtual void __on_zero_shared_weak() _NOEXCEPT;};template void__shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT{ typedef typename __allocator_traits_rebind<_Alloc, __shared_ptr_pointer>::type _Al; typedef allocator_traits<_Al> _ATraits; typedef pointer_traits _PTraits; _Al __a(__data_.second()); __data_.second().~_Alloc(); __a.deallocate(_PTraits::pointer_to(*this), 1);}template void__shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared() _NOEXCEPT // 核心,释放资源{ __data_.first().second()(__data_.first().first()); // 对资源指针调用deleter __data_.first().second().~_Dp();}class _LIBCPP_TYPE_VIS __shared_weak_count : private __shared_count{ long __shared_weak_owners_;public: _LIBCPP_INLINE_VISIBILITY explicit __shared_weak_count(long __refs = 0) _NOEXCEPT // 注意:这里是从0起 : __shared_count(__refs), __shared_weak_owners_(__refs) {}protected: virtual ~__shared_weak_count();public: _LIBCPP_INLINE_VISIBILITY void __add_shared() _NOEXCEPT { __shared_count::__add_shared(); } _LIBCPP_INLINE_VISIBILITY void __add_weak() _NOEXCEPT { __libcpp_atomic_refcount_increment(__shared_weak_owners_); } _LIBCPP_INLINE_VISIBILITY void __release_shared() _NOEXCEPT { if (__shared_count::__release_shared()) __release_weak(); } void __release_weak() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY long use_count() const _NOEXCEPT {return __shared_count::use_count();} __shared_weak_count* lock() _NOEXCEPT;private: virtual void __on_zero_shared_weak() _NOEXCEPT = 0;};void__shared_weak_count::__release_weak() _NOEXCEPT{ // NOTE: The acquire load here is an optimization of the very // common case where a shared pointer is being destructed while // having no other contended references. // // BENEFIT: We avoid expensive atomic stores like XADD and STREX // in a common case. Those instructions are slow and do nasty // things to caches. // // IS THIS SAFE? Yes. During weak destruction, if we see that we // are the last reference, we know that no-one else is accessing // us. If someone were accessing us, then they would be doing so // while the last shared / weak_ptr was being destructed, and // that's undefined anyway. // // If we see anything other than a 0, then we have possible // contention, and need to use an atomicrmw primitive. // The same arguments don't apply for increment, where it is legal // (though inadvisable) to share shared_ptr references between // threads, and have them all get copied at once. The argument // also doesn't apply for __release_shared, because an outstanding // weak_ptr::lock() could read / modify the shared count. if (__libcpp_atomic_load(&__shared_weak_owners_, _AO_Acquire) == 0) { // no need to do this store, because we are about // to destroy everything. //__libcpp_atomic_store(&__shared_weak_owners_, -1, _AO_Release); __on_zero_shared_weak(); } else if (__libcpp_atomic_refcount_decrement(__shared_weak_owners_) == -1) __on_zero_shared_weak();}__shared_weak_count*__shared_weak_count::lock() _NOEXCEPT{ long object_owners = __libcpp_atomic_load(&__shared_owners_); while (object_owners != -1) { if (__libcpp_atomic_compare_exchange(&__shared_owners_, &object_owners, object_owners+1)) return this; } return nullptr;}class _LIBCPP_TYPE_VIS __shared_count{ __shared_count(const __shared_count&); __shared_count& operator=(const __shared_count&);protected: long __shared_owners_; virtual ~__shared_count();private: virtual void __on_zero_shared() _NOEXCEPT = 0;public: _LIBCPP_INLINE_VISIBILITY explicit __shared_count(long __refs = 0) _NOEXCEPT // 注意:这里是从0起 : __shared_owners_(__refs) {} _LIBCPP_INLINE_VISIBILITY void __add_shared() _NOEXCEPT { __libcpp_atomic_refcount_increment(__shared_owners_); // 原子操作引用计数加1 } _LIBCPP_INLINE_VISIBILITY bool __release_shared() _NOEXCEPT { if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) { // 原子操作引用计数减1,当__shared_owners_为-1的时候释放资源 __on_zero_shared(); // 注意,如果在这里另一个线程拷贝构造了这个shared_ptr,会有问题 return true; } return false; } _LIBCPP_INLINE_VISIBILITY long use_count() const _NOEXCEPT { return __libcpp_relaxed_load(&__shared_owners_) + 1; // 返回引用计数 }};