boost库中对sp_counted_base实现根据不同的体系配备了不同的实现体,这里主要分析x86体系下的gcc实现版本。

在正式介绍该函数之前,需要介绍三个函数的实现。

inline int atomic_exchange_and_add( int * pw, int dv ),这个函数的作用:

1. 返回pw存放的数值

2. 修改*pw = *pw + dv

只不过这两个操作都是原子操作,通过在锁操作数地址的情况下,xadd指令完成交换和加法操作。

inline void atomic_increment( int * pw ),该函数作用:

原子对pw里面存放的数值递增,也是在锁操作数地址的情况下,通过incl指令完成

inline int atomic_conditional_increment( int * pw ),该函数作用:

if(*pw) ++*pw

并返回修改前pw存放的数值,这里采用的是cmpxchgl指令,具体代码如下:

    int rv, tmp;__asm__("movl %0, %%eax\n\t""0:\n\t""test %%eax, %%eax\n\t""je 1f\n\t""movl %%eax, %2\n\t""incl %2\n\t""lock\n\t""cmpxchgl %2, %0\n\t""jne 0b\n\t""1:":"=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)"m"( *pw ): // input (%3)"cc" // clobbers);

1. 将*pw存放的数值放入到eax寄存器中

2. 开始判断,如果eax寄存器中保存的数值=0,那么跳到7

3. 将eax里面的数值存放一份到tmp中

4. 对tmp里面的数值进行+1操作

5. 如果*pw里面的数值等于eax里面的数值(如果我们在将*pw的数值取出来之后,后续操作并没有改变*pw),那么将tmp数值写入到pw位置,并设置ZF=1,否则,将*pw里面的数值放入到eax中,也就是重新更新了eax里面的数值,让eax永远等于*pw里面存放的数值

6. 如果在我们准备修改*pw之前,*pw数值已经发生改变,说明这时候我们不能对*pw进行修改,否则会出现写后写的错误情况,此时就应该重新获取新的*pw,并在新的*pw上进行操作,并尝试在此对*pw进行修改,即跳转到2处。如果上步骤修改成功,那么就返回修改前的*pw数值

7. 返回*pw修改前的数值

sp_counted_base是包含在boost::detail命名空间下的一个类,大致原型如下:

<span style="font-size:18px;">class sp_counted_base
{
private:sp_counted_base( sp_counted_base const & );sp_counted_base & operator= ( sp_counted_base const & );int use_count_;        // #sharedint weak_count_;       // #weak + (#shared != 0)
public:sp_counted_base(): use_count_( 1 ), weak_count_( 1 ){}virtual ~sp_counted_base() // nothrow{}virtual void dispose() = 0; // nothrowvirtual void destroy() // nothrow{delete this;}virtual void * get_deleter( sp_typeinfo const & ti ) = 0;virtual void * get_untyped_deleter() = 0;void add_ref_copy(){atomic_increment( &use_count_ );}bool add_ref_lock() // true on success{return atomic_conditional_increment( &use_count_ ) != 0;}void release() // nothrow{if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ){dispose();weak_release();}}void weak_add_ref() // nothrow{atomic_increment( &weak_count_ );}void weak_release() // nothrow{if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ){destroy();}}long use_count() const // nothrow{return static_cast<int const volatile &>( use_count_ );}
};</span>

首先从这个类的构造函数入口,其复制构造函数和赋值构造函数被声明为private,这样就避免了通过复制和赋值操作来产生一个新的对象

那么新的对象如何产生呢?

只能通过定义来产生一个默认的对象,并且这个对象里面的两个成员变量都被赋值为默认值,也就是不能再构造这个对象的时候手动的指定成员变量的值。说到成员变量,sp_counted_base有两个私有的成员变量。

use_count_,主要用于shared_ptr智能指针用来管理计数的。在后续的shared_ptr章节会有介绍。

weak_count_,用于weak_ptr智能指针用来管理计数的,在后续的weak_ptr会介绍。

说完构造函数,析构函数就比较简单了,由于这个类没有管理动态资源,故析构函数是一个空函数,并且实现为虚函数,主要用于管理子类的时候能够正确的调用子类的析构函数,而非错误的调用父类的析构函数。

  • destroy函数,这个函数就是去销毁一个对象,当然这个对象可能是自身或者子类,也定义为虚函数,方便后续不同的子类来复写,从而实现多态。
  • use_count函数,这个函数申明为const类型,表明这个函数不会对对象中的变量进行修改,返回use_count_变量的数值,只不过再返回的时候进行了类型的转换,这里使用了const volatile两个来修饰,说明这个变量首先对于返回值来说是一个常量,同时volatile同时告诉编译器这个常量的读取不能够从缓存在寄存器中进行读取,而要从内存中去读取,以防止数据的不一致性。
  • add_ref_copy函数,调用atomic_increament函数对use_count_变量进行原子+1操作,这个函数主要供shared_ptr调用
  • add_ref_lock函数,调用atomic_conditional_increament函数对use_count_变量+1操作,主要用于weak_ptr到shared_ptr转换时候使用,因为一个weak_ptr对象,如果计数为0,那么就无法转换为一个shared_ptr对象,这里正是通过atomic_conditional_increament函数来正确的管理计数。
  • weak_add_ref函数,类型于add_ref_copy,只不过区别是对weak_count_变量+1操作
  • weak_release函数,进行两部操作,首先将weak_count_修改为weak_count_-1,然后判断weak_count以前的数值是否为1,如果为1说明目前这个调用weak_release函数的对象是最后一个拥有某项资源的对象,那么就调用destory来释放这个对象,当然根据destory函数是一个虚函数,会释放具体的子类。
  • release函数,这个函数是对use_count_变量进行类型与weak_release的操作,一点区别是不会直接调用destory函数,取而代之的是调用dispose和weak_release函数,其中dispose函数是一个纯虚函数,需要子类具体实现,目的是用于释放该对象所管理的具体资源,也就是给资源销毁一个时机。并通过weak_release来销毁该对象。
  • 还有两个纯虚函数get_deleter和get_untyped_deleter,都需要子类去具体实现。

C++ boost库中的sp_counted_base实现解析相关推荐

  1. boost库中优秀的网络库asio

    文章目录 一.须知 二.ASIO 三.我们将从研究同步操作开始 四.当使用异步操作时,会发生不同的事件序列 五.Proactor模型 六.常用内容 七.C++ 建立本地网络服务器 (Boost.Asi ...

  2. boost库中mutex、condition_variable与mutex::scoped_lock联合使用实现线程之间的通信

    最近在公司负责一个线程池的模块,里面用到了boost库中的mutex.condition_variable与mutex::scoped_lock,在此总结下线程池在使用时的方式和要点,这里记录了线程之 ...

  3. 计算机全国统考操作题解析,电大计算机统考题库中的操作题解析.doc

    电大计算机统考题库中的操作题解析 一.文字处理(一般有2道题目,各8分) 1. 打开考生文件夹下的文件Word2.doc,完成以下操作: (1)设置第一段首字下沉,下沉行数3行,距正文0厘米. (2) ...

  4. C++boost库中sp_counted_impl_x实现解析

    sp_counted_impl_x是一系列的类,这些类都是sp_counted_base的子类, 这些类分别是sp_counted_impl_p,sp_counted_impl_pd,sp_count ...

  5. Boost 库中的实用工具类使用入门

    简介: 实用工具类开发和维护会耗费程序员的时间.Boost 通过提供几个高质量的库,从而简化了此过程,您可以将这些库轻松集成到现有的代码库中.本文简单概述一些较流行的 Boost 实用工具类,并帮助您 ...

  6. 【Boost】boost库中function和bind一起使用的技巧(二)

    与 Boost.Function 一起使用 Boost.Bind 当我们把 Boost.Function 与某个支持参数绑定的库结合起来使用时,事情变得更为有趣.Boost.Bind 为普通函数.成员 ...

  7. 【Boost】boost库中function的用法

    要开始使用 Boost.Function, 就要包含头文件 "boost/function.hpp", 或者某个带数字的版本,从"boost/function/funct ...

  8. 【Boost】boost库中thread多线程详解1——thread入门与简介

    1. 概述 线程就是,在同一程序同一时间内允许执行不同函数的离散处理队列. 这使得一个长时间去进行某种特殊运算的函数在执行时不阻碍其他的函数变得十分重要. 线程实际上允许同时执行两种函数,而这两个函数 ...

  9. 【Boost】boost库中timer定时器

    同步Timer asio中提供的timer名为deadline_timer,它提供了超时计时的功能.首先以一个最简单的同步Timer为例来演示如何使用它. #include <iostream& ...

最新文章

  1. SQL字符串基本操作汇总
  2. WebAPi返回类型到底应该是什么才合适,这是个问题?
  3. 深度学习(10):自然语言处理(转)
  4. mvc 根据模板导出excel,直接导出文件流
  5. JavaWeb项目服务端获取客户端的IP地址
  6. pro缺点和不足 一加7t_看点满满,一用难忘:一加7T上手体验全方位测评
  7. OsgEarth加载shp文件问题以及shp文件介绍
  8. Dispose(bool disposing)模式被破坏
  9. 2017年全国大学生电子竞赛电源A题
  10. (四)HEVC基本理论——变换单元TU
  11. Typora中写论文怎么添加reference(参考文献)
  12. 臀部肌群:肌肉图示和英文名称
  13. 2019最应该投资什么?是你明年的北大核心
  14. 电脑计算机提示msvcr100.dll丢失如何修复,msvcr100.dll丢失的解决方法
  15. 关于IDEA在模块scr鼠标右键没有Servlet的解决方法(多种步骤帮你解决)
  16. 优化家里网速,以TL-WR842N为例
  17. 文章汇总【就R不E让I找D到系列part1】
  18. 【电子学会】2020年06月图形化三级 -- 海底寻宝
  19. (转载)历史——YouTube 上传第一个视频;网易云音乐正式上线;数字音频播放器的发明者出生
  20. 后台:转义英文小括号

热门文章

  1. 4.2.5 预测分析法与预测分析表的构造
  2. 报道 | 香港科技大学三十周年校庆红鸟之夜庆祝晚宴圆满落幕
  3. Redis的客户端Jedis
  4. Rich Dad Poor Dad
  5. 抖音直播流量怎么来?四大渠道告诉你
  6. pytorch实现word_embedding(negative_sampling的skip-gram模型)
  7. 天兔(Lepus)监控系统快速安装部署
  8. 社区社群运营,如何打造火爆营销的方法?
  9. 如何让 PPT 中的多张图大小一致?
  10. leetcode 89