赞
踩
_Mutex_base
using __gnu_cxx::__default_lock_policy; using __gnu_cxx::_Lock_policy; using __gnu_cxx::_S_atomic; using __gnu_cxx::_S_mutex; using __gnu_cxx::_S_single; // 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 }; };
_Lock_policy
相关参见备注2.3.
_Sp_counted_base
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() { if (!_M_add_ref_lock_nothrow()) __throw_bad_weak_ptr(); } bool _M_add_ref_lock_nothrow() noexcept; 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.html if (_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 bool _Sp_counted_base<_S_single>::_M_add_ref_lock_nothrow() noexcept { 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() noexcept { __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() noexcept { // 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; }
__exchange_and_add_dispatch
函数参见备注2.2._M_use_count
、_M_weak_count
初始化为1.这里的逻辑是,当它创建的时候,自己本身就是一个引用计数。_M_dispose
函数是纯虚函数,当_M_use_count
为0时,释放this持有的资源。_M_destroy
函数默认删除this,当_M_weak_count
为0时调用。_M_add_ref_copy
函数,对_M_use_count + 1
,是原子操作。_M_add_ref_lock
函数,主要逻辑仍然是_M_use_count + 1
。和_M_add_ref_copy
的区别是对不同_Lock_policy
有不同的实现,包含直接加、原子操作加、加锁。_M_release
函数,当_M_use_count-1=0
时,即_M_use_count
为0时,调用_M_dispose
。并当_M_use_count-1=0
,即_M_weak_count
为0时,调用_M_destroy
。_M_weak_add_ref
:对_M_weak_count + 1
,是原子操作。_M_weak_release
:只对_M_weak_count - 1
。_Lock_policy=_M_single
时的重载形式。_Sp_counted_ptr
// Counted ptr with no deleter or allocator support 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; }; template <> inline void _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { } template <> inline void _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { } template <> inline void _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { }
不支持deleter和allocator的counted ptr。
_M_dispose
默认行为是delete _M_ptr
,_M_destroy
默认行为是delete this。_Ptr=nullptr_t
时,不同_Lock_policy
的_M_dispose
的行为都是空的。_Sp_ebo_helper
template <int _Nm, typename _Tp, bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)> struct _Sp_ebo_helper; /// Specialization using EBO. template <int _Nm, typename _Tp> struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp { explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { } explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { } static _Tp& _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); } }; /// Specialization not using EBO. template <int _Nm, typename _Tp> struct _Sp_ebo_helper<_Nm, _Tp, false> { explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { } explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { } static _Tp& _S_get(_Sp_ebo_helper& __eboh) { return __eboh._M_tp; } private: _Tp _M_tp; };
在类型_Tp
为final且empty的时候,使用ebo优化的类,即模板参数__use_ebo
为true的时候。
_S_get
返回强转为_Tp
类型的入参_Sp_ebo_helper
。_Tp
类型的私有变量:_M_tp
。_S_get
返回这个变量。_Sp_counted_deleter
// Support for custom deleter and/or allocator template <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 : _Del_base(std::move(__d)), _Alloc_base(__a), _M_ptr(__p) { } _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 type_info& __ti [[__gnu__::__unused__]]) 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; #else return nullptr; #endif } private: _Impl _M_impl; };
_Impl
继承自_Sp_ebo_helper<0, _Deleter>
作为_Del_base
、_Sp_ebo_helper<1, _Alloc>
作为_Alloc_base
。
_M_ptr
作为私有变量是被管理的对象的指针。_M_del
从_Del_base
获取一个_Deleter
变量。_M_alloc
从_Alloc_base
获取一个_Alloc
类型变量。_Sp_counted_deleter
继承自_Sp_counted_base
。
_Impl
类型的。_Impl
。_M_dispose
函数对_Ptr
调用_M_del()
。_M_destroy
函数对this调用析构函数。_M_get_delter
,当传入的type_info
类型的__ti
和_Deleter
是同样的类型的时候,返回_M_del()
的地址,否则返回nullptr。_Sp_counted_ptr_inplace
struct _Sp_make_shared_tag { private: template <typename _Tp, typename _Alloc, _Lock_policy _Lp> friend class _Sp_counted_ptr_inplace; static const type_info& _S_ti() noexcept _GLIBCXX_VISIBILITY(default) { alignas(type_info) static constexpr char __tag[sizeof(type_info)] = { }; return reinterpret_cast<const type_info&>(__tag); } static bool _S_eq(const type_info&) noexcept; }; template <typename _Alloc> struct _Sp_alloc_shared_tag { const _Alloc& _M_a; }; 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>; // Alloc parameter is not a reference so doesn't alias anything in __args 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>::construct allocator_traits<_Alloc>::construct(__a, _M_ptr(),
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。