tss.hpp定义了thread_specific_ptr,使用thread local storage 技术

1.在thread目录下的win32和pthread目录下thread_data.hpp定义了两个重要struct:tss_data_node和thread_data_base

struct tss_data_node    //tss_data_node对应相应线程
{
boost::shared_ptr<boost::detail::tss_cleanup_function> func;  //func是thread_specific_ptr的删除器
void* value;                              //thread_local_storage value tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
void* value_):func(func_),value(value_)
{}
};
  typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
struct BOOST_THREAD_DECL thread_data_base:enable_shared_from_this<thread_data_base>
{
  thread_data_ptr self;      //shared_ptr<thread_data_base>
  pthread_t thread_handle;
  boost::mutex data_mutex;
  boost::condition_variable done_condition;
  boost::mutex sleep_mutex;
  boost::condition_variable sleep_condition;
  bool done;
  bool join_started;
  bool joined;
  boost::detail::thread_exit_callback_node* thread_exit_callbacks;
  std::map<void const*,boost::detail::tss_data_node> tss_data;    //tss local storage ,thread_specific_ptr的this作为key,
                                         //tss_data_node保存thread_specific_ptr的value作为 tss_data的value   pthread_mutex_t* cond_mutex;
  pthread_cond_t* current_cond;
  typedef std::vector<std::pair<condition_variable*, mutex*>> notify_list_t;
  notify_list_t notify;   typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
  async_states_t async_states_;   bool interrupt_enabled;
  bool interrupt_requested;
  thread_data_base():
      thread_handle(0),
      done(false),join_started(false),joined(false),
      thread_exit_callbacks(0),
      cond_mutex(0),
      current_cond(0),
      notify(),
      async_states_(), interrupt_enabled(true), interrupt_requested(false)
  {}
  virtual ~thread_data_base();   typedef pthread_t native_handle_type;   virtual void run()=0;
  virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
  {
    notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
  }   void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
  {
    async_states_.push_back(as);
  } };

2. boost::thread类里有个私有指针detail::thread_data_ptr thread_info;说明每个thread都对应了一个thread_data_base

class thread_data:public detail::thread_data_base
{
  private:
    F f;  //thread_data继承于thread_data_base并且 f保存函数
};
template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9): //thread初始化最多带9个参数
  thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
{
  start_thread();
} explicit thread(BOOST_THREAD_RV_REF(F) f
//, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
{
start_thread();
}

在start_thread.cpp运行 start_thread_noexcept()

 int res = pthread_create(&thread_info->thread_handle, h, &thread_proxy, thread_info.get());

thread_proxy

static void* thread_proxy(void* param)
{
//boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->shared_from_this();
thread_info->self.reset();
detail::set_current_thread_data(thread_info.get());    //调用pthread_setspecific
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
BOOST_TRY
{
#endif
thread_info->run();
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS }
BOOST_CATCH (thread_interrupted const&)
{
} BOOST_CATCH_END
#endif
detail::tls_destructor(thread_info.get());
detail::set_current_thread_data();
boost::lock_guard<boost::mutex> lock(thread_info->data_mutex);
thread_info->done=true;
thread_info->done_condition.notify_all(); return ;
}

3.pthread_getspecific和pthread_setspecific。pthread_getpecific和pthread_setspecific实现同一个线程中不同函数间共享数据的一种很好的方式。这里一个线程共享的是

thread_data_ptr thread_info
boost::detail::thread_data_base* get_current_thread_data()
{
  boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
  return (boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key);
} void set_current_thread_data(detail::thread_data_base* new_data)
{
boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data));
}

4.tss_cleanup_function

namespace detail
{
  struct tss_cleanup_function
{
  virtual ~tss_cleanup_function()
{} virtual void operator()(void* data)=;
}; BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
BOOST_THREAD_DECL void* get_tss_data(void const* key);
}

首先定义了一个虚结构体,并重载了运算符()并定义成纯虚函数,tss_cleanup_function可以看成是一个函数对象

5.delete_data和run_custom_cleanup_function

struct delete_data: detail::tss_cleanup_function
{
void operator()(void* data)
{
delete static_cast<T*>(data);
}
};
struct run_custom_cleanup_function:  detail::tss_cleanup_function
{
  void (*cleanup_function)(T*);

  explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
            cleanup_function(cleanup_function_)
{} void operator()(void* data)
{
  cleanup_function(static_cast<T*>(data));
}
};
 boost::shared_ptr<detail::tss_cleanup_function> cleanup;

在thread_specific_ptr类里面定义了delete_data和run_custom_cleanup_function,继承tss_cleanup_function,定义运算符(),作用都是清楚 T*data,delete_data是delete T* data,而run_custom_cleaup_function指定函数指针。所以thread_specific_ptr构造时,默认构造函数 shared_ptr cleanup 指向delete_data,构造函数指定函数指针,cleanup初始化为run_custom_cleanup_function对象

6.以thread_specific_ptr默认构造函数为例

thread_specific_ptr():
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
{}

heap_new在堆上生成delete_data对象并返回指针,do_heap_delete指定删除器

7.set_tss_data和get_tss_data具体实现在win32下boost_1_64_0\libs\thread\src\win32\thread.cpp,Linux在boost_1_64_0/libs/thread/src/pthread/thread.cpp

void* get_tss_data(void const* key)
{
if(tss_data_node* const current_node=find_tss_data(key))
{
return current_node->value;
}
return NULL;
}

void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing)
{
  if(tss_data_node* const current_node=find_tss_data(key))
  {
    if(cleanup_existing && current_node->func && (current_node->value!=0))
    {
    (*current_node->func)(current_node->value);
    }
    if(func || (tss_data!=0))
    {
      current_node->func=func;
      current_node->value=tss_data;
    }
    else
    {
      erase_tss_node(key);
    }
  }
  else if(func || (tss_data!=0))
  {
    add_new_tss_node(key,func,tss_data);
  }
 }

void add_new_tss_node(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data)
{
  detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
  current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(func,tss_data)));
}

 

8. set_tss_data和get_tss_data都会调用find_tss_data(key)来找到tss_data_node,

        tss_data_node* find_tss_data(void const* key)
{
detail::thread_data_base* const current_thread_data(get_current_thread_data()); //获得当前线程thread_data_base
if(current_thread_data)
{
std::map<void const*,tss_data_node>::iterator current_node=
current_thread_data->tss_data.find(key);
if(current_node!=current_thread_data->tss_data.end())
{
return &current_node->second;
}
}
return ;
}
 boost::detail::thread_data_base* get_current_thread_data()
{
  boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
  return (boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key);
} void set_current_thread_data(detail::thread_data_base* new_data)
{
   boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
  BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data));
}

总结:

boost实现tss原理是:每个thread保存一个thread_data_base,thread_data_base里面有tss_map,tss_map将thread_specific_ptr<T>地址作为key,T* new_value保存到

tss_data_node作为tss_map的value。并且使用pthread_getspecific和pthread_setspecific共享thread里thread_data_base的智能指针 thread_data_ptr thread_info

boost tss.hpp源码分析的更多相关文章

  1. 比特币源码分析--C++11和boost库的应用

    比特币源码分析--C++11和boost库的应用     我们先停下探索比特币源码的步伐,来分析一下C++11和boost库在比特币源码中的应用.比特币是一个纯C++编写的项目,用到了C++11和bo ...

  2. Mesos源码分析(12): Mesos-Slave接收到RunTask消息

    在前文Mesos源码分析(8): Mesos-Slave的初始化中,Mesos-Slave接收到RunTaskMessage消息,会调用Slave::runTask.   void Slave::ru ...

  3. Duilib源码分析(六)整体流程

    在<Duilib源码分析(一)整体框架>.<Duilib源码分析(二)控件构造器—CDialogBuilder>以及<Duilib源码分析(三)XML解析器—CMarku ...

  4. folly::AtomicHashmap源码分析(二)

    本文为原创,转载请注明:http://www.cnblogs.com/gistao/ 背景 上一篇只是细致的把源码分析了一遍,而源码背后的设计思想并没有写,设计思想往往是最重要的,没有它,基本无法做整 ...

  5. linux源码分析2

    linux源码分析 这里使用的linux版本是4.8,x86体系. 这篇是 http://home.ustc.edu.cn/~boj/courses/linux_kernel/1_boot.html  ...

  6. Solr4.8.0源码分析(8)之Lucene的索引文件(1)

    Solr4.8.0源码分析(8)之Lucene的索引文件(1) 题记:最近有幸看到觉先大神的Lucene的博客,感觉自己之前学习的以及工作的太为肤浅,所以决定先跟随觉先大神的博客学习下Lucene的原 ...

  7. zeromq源码分析笔记之线程间收发命令(2)

    在zeromq源码分析笔记之架构说到了zmq的整体架构,可以看到线程间通信包括两类,一类是用于收发命令,告知对象该调用什么方法去做什么事情,命令的结构由command_t结构体确定:另一类是socke ...

  8. OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波

    http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...

  9. 【精】EOS智能合约:system系统合约源码分析

    系统合约在链启动阶段就会被部署,是因为系统合约赋予了EOS链资源.命名拍卖.基础数据准备.生产者信息.投票等能力.本篇文章将会从源码角度详细研究system合约. 关键字:EOS,eosio.syst ...

随机推荐

  1. 问题集录01--java对list列表进行排序

    用Collections.sort方法对list排序有两种方法 第一种是list中的对象实现Comparable接口,如下: /** * 根据order对User排序 */ public class  ...

  2. Js 合并 table 行 的实现方法

    Js 合并 table 行 的实现方法 需求如下: 某公司的员工档案,如下,  经理看员工的信息不是很清晰: 姓名 所在学校 毕业时间 张三 小学 2000 张三 中学 2006 张三 大学 2010 ...

  3. UML关系

    UML关系详解 1.关联关系(association) 连接模型元素及链接实例,用一条实线来表示 2.依赖关系(dependency) 表示一个元素以某种方式依赖于另一个元素,用一条虚线加箭头来表示 ...

  4. Nodejs 8.0 踩坑经验汇总

    .Linq:Linq to sql 类 高度集成化的数据库访问技术 使用Linq是应该注意的问题: 1.创建Linq连接后生成的dbml文件不要变动,生成的表不要碰,拖动表也会造成数据库连接发生变动, ...

  5. 一个骚气的前端JS代码生成网站

    生成Javascript 颜文字代码 稍微试了试 原本的代码: alert("Hello, JavaScript") 转换后代码 ゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`* ...

  6. C#项目””是针对”.NETFramework,Version=v4.5.2”但此计算机没有,需要修改为v4.5.1.

    每次下载别人的代码都会出现这样的问题,以为是没有安装.NETFramework,就下载安装了,但是每次安装都会出现已安装高版本的4.6(Win10自带),无需下次安装,但是每次VS中都会显示有问题,而 ...

  7. javascript获取文件后缀名

    javascript获取文件后缀名:在需要验证文件格式的时候,首先就要获得文件的格式,下面是一个通过正则表达式获取文件后缀名的一个简单实例. function validate(){ var impo ...

  8. IE6 行内定义成块元素后高度失效

    问题描述: ie6下,空标签块元素height定义失效,表现为除设置的height值外还会显示N像素额外的高度. 实际运用中,若标签为空且定义了小于14px的高度,再加入一背景图的话,会发现该元素高度 ...

  9. ogr2ogr使用

    简介 org2ogr是OGR模块中提供的一个重要工具,用于对数据源进行格式转换 使用方式 命令行参数 [xingxing.dxx@30_28_6_20 J50F001020]$ ogr2ogr --l ...

  10. Codeforces Round #411 A. Fake NP

    A. Fake NP time limit per test   1 second memory limit per test   256 megabytes   Tavak and Seyyed a ...