muduo库中线程本地单例类封装代码是ThreadLocalSingleton.h

如下所示:

//线程本地单例类封装
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com) #ifndef MUDUO_BASE_THREADLOCALSINGLETON_H
#define MUDUO_BASE_THREADLOCALSINGLETON_H #include <boost/noncopyable.hpp>
#include <assert.h>
#include <pthread.h> namespace muduo
{ template<typename T>
class ThreadLocalSingleton : boost::noncopyable//不可被拷贝
{
public:
//返回单例对象的引用
static T& instance()
{
if (!t_value_)//如果指针为空
{
t_value_ = new T();//创建对象
deleter_.set(t_value_);//将t_value_传入deleter_,以便deleter_可以调用destructor销毁
}
return *t_value_;//返回
}
//返回单例对象的指针
static T* pointer()
{
return t_value_;
} private:
//销毁对象
static void destructor(void* obj)
{
assert(obj == t_value_);
typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
delete t_value_;
t_value_ = 0;
}
//一个嵌套类只是为了能够调用destructor自动销毁t_value_
class Deleter
{//借助线程特定数据来实现
public:
Deleter()//构造函数的回调函数为ThreadLocalSingleton::destructor
{
pthread_key_create(&pkey_, &ThreadLocalSingleton::destructor);
} ~Deleter()
{
pthread_key_delete(pkey_);
} void set(T* newObj)
{
assert(pthread_getspecific(pkey_) == NULL);
pthread_setspecific(pkey_, newObj);
} pthread_key_t pkey_;
}; static __thread T* t_value_;//T类型的指针,__thread关键字表示每个线程都有一份
static Deleter deleter_;//主要用于销毁上面那个指针所指向的对象
}; template<typename T>
__thread T* ThreadLocalSingleton<T>::t_value_ = 0; template<typename T>
typename ThreadLocalSingleton<T>::Deleter ThreadLocalSingleton<T>::deleter_; }
#endif

测试程序如下:

//线程本地单例类封装测试程序
#include <muduo/base/ThreadLocalSingleton.h>
#include <muduo/base/CurrentThread.h>
#include <muduo/base/Thread.h> #include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <stdio.h> class Test : boost::noncopyable
{
public:
Test()
{
printf("tid=%d, constructing %p\n", muduo::CurrentThread::tid(), this);
} ~Test()
{
printf("tid=%d, destructing %p %s\n", muduo::CurrentThread::tid(), this, name_.c_str());
} const std::string& name() const { return name_; }
void setName(const std::string& n) { name_ = n; } private:
std::string name_;
}; void threadFunc(const char* changeTo)
{//打印线程tid,线程单例对象地址,线程单例对象名称
printf("tid=%d, %p name=%s\n",
muduo::CurrentThread::tid(),
&muduo::ThreadLocalSingleton<Test>::instance(),
muduo::ThreadLocalSingleton<Test>::instance().name().c_str());
//重新设置一下名称
muduo::ThreadLocalSingleton<Test>::instance().setName(changeTo);
//再次打印
printf("tid=%d, %p name=%s\n",
muduo::CurrentThread::tid(),
&muduo::ThreadLocalSingleton<Test>::instance(),
muduo::ThreadLocalSingleton<Test>::instance().name().c_str());
//线程退出时会自动销毁,对象周期结束
// no need to manually delete it
// muduo::ThreadLocalSingleton<Test>::destroy();
} int main()
{//muduo::ThreadLocalSingleton<Test>::instance()返回一个线程单例对象,每个线程都有一个Test对象
muduo::ThreadLocalSingleton<Test>::instance().setName("main one");
//创建两个线程,threadFunc为回调函数
muduo::Thread t1(boost::bind(threadFunc, "thread1"));
muduo::Thread t2(boost::bind(threadFunc, "thread2"));
//启动两个线程
t1.start();
t2.start();
t1.join();
//打印主线程的
printf("tid=%d, %p name=%s\n",
muduo::CurrentThread::tid(),
&muduo::ThreadLocalSingleton<Test>::instance(),
muduo::ThreadLocalSingleton<Test>::instance().name().c_str());
t2.join();
//退出主线程
pthread_exit(0);
}

运行结果如下:

muduo网络库源码学习————线程本地单例类封装的更多相关文章

  1. muduo网络库源码学习————线程特定数据

    muduo库线程特定数据源码文件为ThreadLocal.h //线程本地存储 // Use of this source code is governed by a BSD-style licens ...

  2. muduo网络库源码学习————线程池实现

    muduo库里面的线程池是固定线程池,即创建的线程池里面的线程个数是一定的,不是动态的.线程池里面一般要包含线程队列还有任务队列,外部程序将任务存放到线程池的任务队列中,线程池中的线程队列执行任务,也 ...

  3. muduo网络库源码学习————线程类

    muduo库里面的线程类是使用基于对象的编程思想,源码目录为muduo/base,如下所示: 线程类头文件: // Use of this source code is governed by a B ...

  4. muduo网络库源码学习————线程安全

    线程安全使用单例模式,保证了每次只创建单个对象,代码如下: Singleton.h // Use of this source code is governed by a BSD-style lice ...

  5. muduo网络库源码学习————Timestamp.cc

    今天开始学习陈硕先生的muduo网络库,moduo网络库得到很多好评,陈硕先生自己也说核心代码不超过5000行,所以我觉得有必要拿过来好好学习下,学习的时候在源码上面添加一些自己的注释,方便日后理解, ...

  6. muduo网络库源码学习————互斥锁

    muduo源码的互斥锁源码位于muduo/base,Mutex.h,进行了两个类的封装,在实际的使用中更常使用MutexLockGuard类,因为该类可以在析构函数中自动解锁,避免了某些情况忘记解锁. ...

  7. muduo网络库源码学习————日志滚动

    muduo库里面的实现日志滚动有两种条件,一种是日志文件大小达到预设值,另一种是时间到达超过当天.滚动日志类的文件是LogFile.cc ,LogFile.h 代码如下: LogFile.cc #in ...

  8. muduo网络库源码学习————日志类封装

    muduo库里面的日志使方法如下 这里定义了一个宏 #define LOG_INFO if (muduo::Logger::logLevel() <= muduo::Logger::INFO) ...

  9. muduo网络库源码学习————无界队列和有界队列

    muduo库里实现了两个队列模板类:无界队列为BlockingQueue.h,有界队列为BoundedBlockingQueue.h,两个测试程序实现了生产者和消费者模型.(这里以无界队列为例,有界队 ...

随机推荐

  1. jvm入门及理解(二)——类加载器子系统

    一.类加载子系统的作用 类加载子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识: ClassLoader只负责class文件的加载,至于它是否可以运行,则由E ...

  2. C# 基础知识系列- 9 字符串的更多用法(一)

    0. 前言 在前面的文章里简单介绍了一下字符串的相关内容,并没有涉及到更多的相关内容,这一篇将尝试讲解一下在实际开发工作中会遇到的字符串的很多操作. 1. 创建一个字符串 这部分介绍一下如何创建一个字 ...

  3. k8s pod yaml参数说明

  4. iOS获取剩余存储空间

    //ios获取剩余存储空间 -(void)usedSpaceAndfreeSpace{ NSString* path = [NSSearchPathForDirectoriesInDomains(NS ...

  5. 012-C语言小游戏之推箱子

    012-C语言小游戏之推箱子 一.创建游戏地图   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #define ROWS 11 #define COLS 12   char ...

  6. 【翻译】Java Array的排名前十方法(Top 10 Methods for Java Arrays)

    这里列举了Java Array 的前十的方法.他们在stackoverflow最大投票的问题. The following are top 10 methods for Java Array. The ...

  7. Cobalt Stike使用教程

    目录: 安装与连接 监听器Listner 基本使用方法--Cobalt Strike生成后门 Beacon详解 菜单栏与视图 文件管理与进程管理 浏览器代理 Cobalt Strike扩展 提权 横向 ...

  8. B2. Character Swap (Hard Version)

    链接: http://codeforces.com/contest/1243/problem/B2 题目大意: 两个字符串,判断能否通过交换为从而使得这两个字符串完全一致,如不可以的话,直接输出NO, ...

  9. js拼接onclick方法字符串参数解决方法

    onclick = contentmap("'+useridarr[i]+'")

  10. Linux学习笔记(四)帮助命令

    帮助命令 man info help --help man 英文原意:format and display the on-line manual pages 功能:显示联机帮助手册 语法:man 选项 ...