多线程编程中还有一个重要的概念: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. Python 模块(五)

    目录 模块介绍 time &datetime模块 random json & picle 一.模块介绍 在我们日常的程序开发过程中,随着代码越写越多,在单个文件里的代码就会越来越长,越 ...

  2. 语法糖----JAVA

    语法糖 语法糖(Syntactic Sugar),也叫糖衣语法,是英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语.指的是,在计算机语言中添加某种语法,这种语法能使程序 ...

  3. TensorFlow文本与序列的深度模型

    TensorFlow深度学习笔记 文本与序列的深度模型 Deep Models for Text and Sequence 转载请注明作者:梦里风林Github工程地址:https://github. ...

  4. MessageBox不能前置显示的问题

    在MFC的开发中,经常会遇到一些莫名奇妙的问题,可能是经验不足的原因吧. 进入正题....在手头的项目中,用MFC做的界面应用.在某一天突然发现程序界面不能进行响应,经过反复的调试后发现:Messag ...

  5. 为centos添加第三方源

    默认centos自带的源少了很多好软件,所以需要添加第三方源一.安装CentOS yum源优先级插件yum-prioritiesyum install yum-plugin-priorities.no ...

  6. Linux内核空间-用户空间通信之debugfs

    一.debugfs文件系统简介 debugfs虚拟文件系统是一种内核空间与用户空间的接口,基于libfs库实现,专用于开发人员调试,便于向用户空间导出内核空间数据(当然,反方向也可以).debugfs ...

  7. SDCard助手类

    package com.zyh.sdcardHelper; import java.io.BufferedInputStream; import java.io.BufferedOutputStrea ...

  8. 快速傅里叶变换应用之二 hdu 4609 3-idiots

    快速傅里叶变化有不同的应用场景,hdu4609就比较有意思.题目要求是给n个线段,随机从中选取三个,组成三角形的概率. 初始实在没发现这个怎么和FFT联系起来,后来看了下别人的题解才突然想起来:组合计 ...

  9. 自己python程序的并行修改

    遇到运算量大的程序,学习了下python并行运算的方法,在自己的程序上进行了修改,看看是否可以增加效率.原始代码是: import gt_apps as my_apps f=file('sample. ...

  10. 旧版本mysql下载大全,爽~~

    http://mirror.cogentco.com/pub/mysql/MySQL-4.1/ http://mirror.cogentco.com/pub/mysql/MySQL-5.0/ http ...