多线程编程中还有一个重要的概念:Thread Local Store(TLS,线程局部存储),在boost中,TLS也被称作TSS,Thread Specific Storage。
boost::thread库为我们提供了一个接口简单的TLS的面向对象的封装,以下是tss类的接口定义:

class tss
{
public:
    tss(boost::function1<void, void*>* pcleanup);
    void* get() const;
    void set(void* value);
    void cleanup(void* p);
};

分别用于获取、设置、清除线程局部存储变量,这些函数在内部封装了TlsAlloc、TlsGetValue、TlsSetValue等API操作,将它们封装成了OO的形式。
但boost将该类信息封装在detail名字空间内,即不推荐我们使用,当需要使用tss时,我们应该使用另一个使用更加方便的类:thread_specific_ptr,这是一个智能指针类,该类的接口如下:

 1 class thread_specific_ptr : private boost::noncopyable   // Exposition only
 2 {
 3 public:
 4   // construct/copy/destruct
 5   thread_specific_ptr();
 6   thread_specific_ptr(void (*cleanup)(void*));
 7   ~thread_specific_ptr();
 8 
 9   // modifier functions
10   T* release();
11   void reset(T* = 0);
12 
13   // observer functions
14   T* get() const;
15   T* operator->() const;
16   T& operator*()() const;
17 };

即可支持get、reset、release等操作。
thread_specific_ptr类的实现十分简单,仅仅为了将tss类“改装”成智 能指针的样子,该类在其构造函数中会自动创建一个tss对象,而在其析构函数中会调用默认参数的reset函数,从而引起内部被封装的tss对象被析构, 达到“自动”管理内存分配释放的目的。

以下是一个运用thread_specific_ptr实现TSS的例子:

 1 #include <boost/thread/thread.hpp>
 2 #include <boost/thread/mutex.hpp>
 3 #include <boost/thread/tss.hpp>
 4 #include <iostream>
 5 
 6 boost::mutex io_mutex;
 7 boost::thread_specific_ptr<int> ptr;    // use this method to tell that this member will not shared by all threads
 8 
 9 struct count
10 {
11     count(int id) : id(id) { }
12 
13     void operator()()
14     {
15         if (ptr.get() == 0)    // if ptr is not initialized, initialize it
16             ptr.reset(new int(0));    // Attention, we pass a pointer to reset (actually set ptr)
17 
18         for (int i = 0; i < 10; ++i)
19         {
20             (*ptr)++;
21             boost::mutex::scoped_lock lock(io_mutex);
22             std::cout << id << ": " << *ptr << std::endl;
23         }
24     }
25 
26     int id;
27 };
28 
29 int main(int argc, char* argv[])
30 {
31     boost::thread thrd1(count(1));
32     boost::thread thrd2(count(2));
33     thrd1.join();
34     thrd2.join();
35 
36     return 0;
37 }

此外,thread库还提供了一个很有趣的函数,call_once,在tss),如果你将该参数初始化成,则函数func将不被调用,此时call_once相当于什么也没干,这在有时候可能是需要的,比如,根据程序处理的结果决定是否需要call_once某函数func。
call_once在执行完函数func后,会将flag修改为,这样会导致以后执行call_once的线程(包括等待在Mutex处的线程和刚刚进入call_once的线程)都会跳过执行func的代码。

需要注意的是,该函数不是一个模板函数,而是一个普通函数,它的第一个参数是一个函数指针,其类型为void (*)(),而不是跟boost库的很多其它地方一样用的是function模板,不过这样也没有关系,有了boost::bind这个超级武器,想怎么绑定参数就随你的便了,根据boost的文档,要求传入的函数不能抛出异常,但从实现代码中好像不是这样。

以下是一个典型的运用call_once实现一次初始化的例子:

 1 #include <boost/thread/thread.hpp>
 2 #include <boost/thread/once.hpp>
 3 #include <iostream>
 4 
 5 int i = 0;
 6 int j = 0;
 7 boost::once_flag flag = BOOST_ONCE_INIT;
 8 
 9 void init()
10 {
11     ++i;
12 }
13 
14 void thread()
15 {
16     boost::call_once(&init, flag);
17     ++j;
18 }
19 
20 int main(int argc, char* argv[])
21 {
22     boost::thread thrd1(&thread);
23     boost::thread thrd2(&thread);
24     thrd1.join();
25     thrd2.join();
26 
27     std::cout << i << std::endl;
28     std::cout << j << std::endl;
29 
30     return 0;
31 }

结果显示,全局变量i仅被执行了一次++操作,而变量j则在两个线程中均执行了++操作。

Boost Thread学习笔记五的更多相关文章

  1. Boost Thread学习笔记四

    barrierbarrier类的接口定义如下:  1 class barrier : private boost::noncopyable   // Exposition only 2 { 3 pub ...

  2. Boost Thread学习笔记三

    下面先对condition_impl进行简要分析.condition_impl在其构造函数中会创建两个Semaphore(信号量):m_gate.m_queue,及一个Mutex(互斥体,跟boost ...

  3. Boost Thread学习笔记二

    除了thread,boost种:boost::mutexboost::try_mutexboost::timed_mutexboost::recursive_mutexboost::recursive ...

  4. Boost Thread学习笔记

    thread自然是boost::thread库的主 角,但thread类的实现总体上是比较简单的,前面已经说过,thread只是一个跨平台的线程封装库,其中按照所使用的编译选项的不同,分别决定使用 W ...

  5. muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor

    目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...

  6. Java IO学习笔记五:BIO到NIO

    作者:Grey 原文地址: Java IO学习笔记五:BIO到NIO 准备环境 准备一个CentOS7的Linux实例: 实例的IP: 192.168.205.138 我们这次实验的目的就是直观感受一 ...

  7. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  8. (转)Qt Model/View 学习笔记 (五)——View 类

    Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...

  9. java之jvm学习笔记五(实践写自己的类装载器)

    java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...

随机推荐

  1. ecshop后台添加栏目

    ecshop后台增加模块菜单详细教程 一:ecshop后台管理 admin\includes\inc_menu.php 添加上你要添加的功能admin\includes\inc_priv.php 对应 ...

  2. USACO Cow Pedigrees 【Dp】

    一道经典Dp. 定义dp[i][j] 表示由i个节点,j 层高度的累计方法数 状态转移方程为: 用i个点组成深度最多为j的二叉树的方法树等于组成左子树的方法数 乘于组成右子树的方法数再累计. & ...

  3. HDOJ1232 并查集

    所谓并查集 并:Union 查:Find 定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单 ...

  4. iOS5.1下emoji表情显示方框的解决办法

    在iOS5.1的部分设备上,emoji表情无法正常显示.我测试了一下,iOS5.1(9B176 for iPhone 4)无法正常显示emoji,全部是方框iOS5.1(9B179 for iPhon ...

  5. Python 数据处理扩展包: numpy 和 pandas 模块介绍

    一.numpy模块 NumPy(Numeric Python)模块是Python的一种开源的数值计算扩展.这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list str ...

  6. jquey的 ajax请求的几种方式

    在jquery中,提供了集中方法来进行ajax操作 一.$.get(url,[data],[callback]) 向服务器发起get操作. 说明:url为请求地址,data为请求数据的列表(json对 ...

  7. Main方法的执行过程(转)

    要运行一个 main 方法 , 首先要知道 main 方法所在的 Class, 在命令行中指定这个 Class 名 Class Lava{ Private int speed = 4; Void fl ...

  8. javascript语言精粹:继承

    继承提供了2个有用的任务: 1.代码重用 2.引入了一套类型系统的规范,因为程序员无需编写显示类型转换的代码,他们的工作量将大大减轻.这是一件很好的事情,应为类型转换会丧失类型系统在安全上的优势. 在 ...

  9. HDU2191:悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)

    Problem Description 急!灾区的食物依然短缺! 为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品 ...

  10. AsyncTask究竟需要多少个线程

    最起码两个:主线程和工作线程; 可以参考:http://zhidao.baidu.com/link?url=ho4UEcEbaogRZUFHwig1neSKR25b2zT9iXyM36hEgWTmvJ ...