目录

一、关键点解析

1、_Lock_policy解析

2、__default_lock_policy的定义

3、__atomic_add_dispatch解析

4、__attribute__

5、__exchange_and_add_dispatch解析

6、_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE和_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER解析

7、  内存屏障_GLIBCXX_READ_MEM_BARRIER和_GLIBCXX_WRITE_MEM_BARRIER

8、_Sp_counted_base的父类

9、头文件

二、源码解析


一、关键点解析

1、_Lock_policy解析

enum _Lock_policy { _S_single, _S_mutex, _S_atomic };

// Available locking policies:
  // _S_single    single-threaded code that doesn't need to be locked.
  // _S_mutex     multi-threaded code that requires additional support
  //              from gthr.h or abstraction layers in concurrence.h.
  // _S_atomic    multi-threaded code using atomic operations.

2、__default_lock_policy的定义

static const _Lock_policy __default_lock_policy = 
#ifdef __GTHREADS
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) \
     && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4))
  _S_atomic;
#else
  _S_mutex;
#endif
#else
  _S_single;
#endif

3、__atomic_add_dispatch解析

(1)、 __atomic_add_dispatch函数定义

static inline void
  __attribute__ ((__unused__))
  __atomic_add_dispatch(_Atomic_word* __mem, int __val)
  {
#ifdef __GTHREADS//如果定义了多线程
    if (__gthread_active_p())//如果多线程是可用的
      __atomic_add(__mem, __val);
    else
      __atomic_add_single(__mem, __val);
#else
    __atomic_add_single(__mem, __val);
#endif
  }

(2)、其它一些定义

#ifdef _GLIBCXX_ATOMIC_BUILTINS
  static inline _Atomic_word 
  __exchange_and_add(volatile _Atomic_word* __mem, int __val)
  { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }

static inline void
  __atomic_add(volatile _Atomic_word* __mem, int __val)
  { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
#else
  _Atomic_word
  __attribute__ ((__unused__))
  __exchange_and_add(volatile _Atomic_word*, int) throw ();

void
  __attribute__ ((__unused__))
  __atomic_add(volatile _Atomic_word*, int) throw ();
#endif

static inline void
  __atomic_add_single(_Atomic_word* __mem, int __val)
  { *__mem += __val; }

4、__attribute__

GNU C 的一大特色就是__attribute__ 机制。__attribute__ 可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。

__attribute__ 书写特征是:__attribute__ 前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__ 参数。

__attribute__ 语法格式为:__attribute__ ((attribute-list))

5、__exchange_and_add_dispatch解析

static inline _Atomic_word
  __attribute__ ((__unused__))
  __exchange_and_add_dispatch(_Atomic_word* __mem, int __val)
  {
#ifdef __GTHREADS
    if (__gthread_active_p())
      return __exchange_and_add(__mem, __val);
    else
      return __exchange_and_add_single(__mem, __val);
#else
    return __exchange_and_add_single(__mem, __val);
#endif
  }

Both of these functions are declared in the header file <ext/atomicity.h>, and are in namespace __gnu_cxx.

  • __exchange_and_add_dispatch

    Adds the second argument's value to the first argument. Returns the old value.

  • __atomic_add_dispatch

    Adds the second argument's value to the first argument. Has no return value.

6、_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE和_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER解析

// Macros for race detectors.
// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) and
// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) should be used to explain
// atomic (lock-free) synchronization to race detectors:
// the race detector will infer a happens-before arc from the former to the
// latter when they share the same argument pointer.
//
// The most frequent use case for these macros (and the only case in the
// current implementation of the library) is atomic reference counting:
//   void _M_remove_reference()
//   {
//     _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&this->_M_refcount);
//     if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount, -1) <= 0)
//       {
//         _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&this->_M_refcount);
//         _M_destroy(__a);
//       }
//   }
// The annotations in this example tell the race detector that all memory
// accesses occurred when the refcount was positive do not race with
// memory accesses which occurred after the refcount became zero.

All synchronization primitives used in the library internals need to be understood by race detectors so that they do not produce false reports.

Two annotation macros are used to explain low-level synchronization to race detectors: _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE() and _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(). By default, these macros are defined empty -- anyone who wants to use a race detector needs to redefine them to call an appropriate API. Since these macros are empty by default when the library is built, redefining them will only affect inline functions and template instantiations which are compiled in user code. This allows annotation of templates such as shared_ptr, but not code which is only instantiated in the library. Code which is only instantiated in the library needs to be recompiled with the annotation macros defined. That can be done by rebuilding the entire libstdc++.so file but a simpler alternative exists for ELF platforms such as GNU/Linux, because ELF symbol interposition allows symbol7s defined in the shared library to be overridden by symbols with the same name that appear earlier in the runtime search path. This means you only need to recompile the functions that are affected by the annotation macros, which can be done by recompiling individual files.

7、  内存屏障_GLIBCXX_READ_MEM_BARRIER和_GLIBCXX_WRITE_MEM_BARRIER

CPU乱序执行在单线程环境下是一种很好的优化手段,但是在多线程环境下,就会出现数据不一致的问题,因此就可以通过内存屏障这个机制来处理这个问题。

1.写内存屏障(Store Memory Barrier):在指令后插入Store Barrier,能让写入缓存中最新数据更新写入主内存中,让其他线程可见。强制写入主内存,这种显示调用,不会让CPU去进行指令重排序
2.读内存屏障(Load Memory Barrier):在指令后插入Load Barrier,可以让高速缓存中的数据失效,强制重新从主内存中加载数据。也是不会让CPU去进行指令重排。

#ifndef _GLIBCXX_READ_MEM_BARRIER
#define _GLIBCXX_READ_MEM_BARRIER __asm __volatile ("":::"memory")
#endif
#ifndef _GLIBCXX_WRITE_MEM_BARRIER
#define _GLIBCXX_WRITE_MEM_BARRIER __asm __volatile ("":::"memory")
#endif

__asm __volatile ("":::"memory")为汇编代码

creates a compiler level memory barrier forcing optimizer to not re-order memory accesses across the barrier.

For example, if you need to access some address in a specific order (probably because that memory area is actually backed by a different device rather than a memory) you need to be able tell this to the compiler otherwise it may just optimize your steps for the sake of efficiency.

memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令。

这里就是跟编译器说已经更改了内存了。

8、_Sp_counted_base的父类

是继承_Mutex_base 类的(_Mutex_base 类解析可以参考GNU C++ 智能指针2-- 解析_Mutex_base类_kupePoem的专栏-CSDN博客)

9、头文件

类位于shared_ptr_base.h中

二、源码解析

  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){_GLIBCXX_READ_MEM_BARRIER;_GLIBCXX_WRITE_MEM_BARRIER;}// 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()_GLIBCXX_READ_MEM_BARRIER;_GLIBCXX_WRITE_MEM_BARRIER;}_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; }

GNU C++ 智能指针3-- 解析_Sp_counted_base类相关推荐

  1. 智能指针详细解析(智能指针的使用,原理解析)

    本文转自努力的少年博主: https://blog.csdn.net/sjp11/article/details/123899141 目录 一. 智能指针的基本概念 二.  智能指针的定义和使用 三. ...

  2. 智能指针 shared_ptr 解析

    近期正在进行<Effective C++>的第二遍阅读,书里面多个条款涉及到了shared_ptr智能指针,介绍的太分散,学习起来麻烦.写篇blog整理一下. LinJM   @HQU s ...

  3. c语言智能指针是什么,C++ 智能指针深入解析

    1. 为什么需要智能指针?简单的说,智能指针是为了实现类似于Java中的垃圾回收机制.Java的垃圾回收机制使程序员从繁杂的内存管理任务中彻底的解脱出来,在申请使用一块内存区域之后,无需去关注应该何时 ...

  4. GNU C++ 智能指针6-- 解析_Sp_counted_inplace类

    目录 一.关键点解析 1.__gnu_cxx::__aligned_buffer 2.std::forward 3.remove_cv 4.const_cast 二.源码分析 一.关键点解析 1.__ ...

  5. GNU C++ 智能指针5-- 解析_Sp_counted_deleter类

    目录 一.关键点解析 1.头文件 2.ebo 3. _Sp_ebo_helper的定义 4._M_destroy函数解析 二.代码分析 一.关键点解析 1.头文件 shared_ptr_base.h ...

  6. GNU C++ 智能指针4-- 解析_Sp_counted_ptr类

    目录 一.关键点解析 1.final关键字 2.=delete关键字 3.父类 4.noexcept关键字 5.explicit关键字 6.头文件 二.代码分析 一.关键点解析 1.final关键字 ...

  7. 【c++复习笔记】——智能指针详细解析(智能指针的使用,原理分析)

  8. 学习笔记:C++进阶【继承、多态、二叉树进阶、map和set、哈希、C++11、异常、智能指针、特殊类设计、C++的类型转换】

    文章目录 前言 一.继承 1. 继承的概念及定义 1.1 继承的概念 1.2 继承的定义 1.2.1 定义格式 1.2.2 继承关系和访问限定符 1.2.3 继承基类成员访问方式的变化 2. 基类和派 ...

  9. 61、智能指针类模板

    1.智能指针 智能指针的意义 - 现代C++开发库中最重要的类模板之一 - C++中自动内存管理的主要手段 - 能在很大程度上避开内存相关的问题 STL中的智能指针 auto_ptr(#include ...

最新文章

  1. VC++向txt文件中写入字符串
  2. jquery中$each()
  3. 论文学习9-Bidirectional LSTM-CRF Models for Sequence Tagging(LSTM,BILSTM,LSTM-CRF,BILSTM-CRF
  4. 老板催你交圣诞海报设计?PSD源文件素材,直接编辑
  5. EMNLP 2017 北京论文报告会笔记
  6. 使用R语言中的GWmodel进行GWR模型的运算
  7. Java 使用百度翻译-通用翻译API
  8. Word删除表格后空白页的方法
  9. RFID自助借还书的功能介绍
  10. 2022-2028年全球与中国蛋白质补充剂行业市场需求预测分析
  11. 信息化时代下,企业面临的5个数据安全威胁
  12. pcie扰码的作用_物理层逻辑知识,关于扰码器需要遵循的规则
  13. CSDN超级实习生 | 寒假之前,收藏好这份大厂2022年实习生招聘计划
  14. dz2.5 oday
  15. Java、JSP农产品销售系统的设计与实现
  16. php生成手机桌面快捷方式,php生成网页桌面快捷方式
  17. sd卡数据误删怎么恢复?内存卡里的照片删了怎么恢复
  18. 千锋教育威哥学Java—最新Java学习路线图(完整详细版) 千锋Java教学出品
  19. 关于Android全面屏与虚拟按键适配问题
  20. ipad分屏功能怎么开启_iOS 14新功能爆料汇总:安卓用户似曾相识

热门文章

  1. 模仿斗地主玩法实现扑克牌的分发
  2. Android 系统禁用触摸屏
  3. 通过学习RN技术,平常自己的一些笔记整理,希望借鉴
  4. 2021年的诀尘子和Vue
  5. Android Smart Image View
  6. 头歌 6. Pandas合并数据集
  7. c语言case2什么意思,switchCase2
  8. 趣商宝微信招生方案 ,线上招生难,十大绝招帮您搞定微信吸粉!
  9. 小企业仓库管理软件设计开发
  10. 前端处理后端返回的excel文件流并下载