muduo源码分析:ThreadLocalSigleton类

单例+特定数据

// Singleton 所管理的对象是 ThreadLocal<Test> , ThreadLocal<Test> 在进程内是单例, 所有线程共一个ThreadLocal<Test>  实例           Singleton调用instance方法获取 ThreadLocal<Test> 实例, ThreadLocal<Test>实例 调用 ThreadLocal<Test>:: value方法获取Test类型线程特定数据的引用,value返回的是各自线程特定数据引用。 Singleton确保进程范围内单例,ThreadLocal<Test>实例只有一个,所有线程共这一个ThreadLocal<Test>实例 (所以 Singleton内部要加锁初始化实例,或者用pthread_once初始化实例 ;ThreadLocal确保Test有多个,即在每个线程都有自己特定的 (由于 ThreadLocal<Test>已经是单例了,定了不会有新的出现了 pthread_key_t key_一直是那一个,所以其实Test在每个线程也是只有一个,也是线程中的单例

#define STL muduo::Singleton<muduo::ThreadLocal<Test> >::instance().value()

多个线程的instance( ) 返回同一个进程范围内单例实例,value( )返回本线程特定数据实例Test的引用

线程特定+单例:ThreadLocalSigleton

所有线程都有自己的一份,且都只有一个,即在线程范围内它是单例,一直存在的,静态的,

ThreadLocalSigleton<Test> ::instance( ): 返回本线程Test单例实例的引用,线程内单例.每次都是这一个static __pthreadT*

ThreadLocal<Test> t:每调用默认构造函数(没有括号,参数),每次都会new 一个Test 实例 t 给本线程


muduo::Singleton<muduo::ThreadLocal<Test> >::instance().value() 与 ThreadLocalSigleton<Test> ::instance( ) 

两者其实都是在线程中实现了单例,效果一样

#ifndef MUDUO_BASE_THREADLOCALSIGLETON_H
#define MUDUO_BASE_THREADLOCALSIGLETON_H

#include <boost/noncopyable.hpp>
#include <assert.h>
#include <pthread.h>

namespace muduo
{

template<typename T>
class ThreadLocalSingleton : boost::noncopyable
{
public:
	//注意是静态,获取同一个实例-单例,t_value_ 是__thread 修饰的,线程私有,所以不要加锁
	static T& instance()
	{
		if(t_value_ == NULL)
		{	
			t_value_ = new T();
			deleter_.set(t_value_);//注册删除释放,t_value_指针在pthread_key_t中也存了一份,用于删除释放内存
		}
		return *t_value_;
	}
	static T* pointer()
	{
		return t_value_;
	}
	private:
			//ThreadLocalSingleton只提供了静态方法instance(),获取单例用的是静态方法,没有实例化对象,所以就没有析构,就不要在析构函数中释放T*;即使用成员非静态instance(先实例化ThreadLocalSingleton),如果析构函数中释放了T*,那下次获取的时候会是重新new的,那就不是单例了
	static void destructor(void* obj)
	{
		assert(obj == t_value_);//
		typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
    	T_must_be_complete_type tt;(void) tt;
		delete t_value_;
    	t_value_ = 0;
	}

	class Deleter
	{
	public:
		Deleter()
		{
			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_;
	};
private:
	static __thread T* t_value_;//单例,线程生命周期内都只有一个T*,所以要静态
	static Deleter deleter_;//整个进程只需要一个pthread_key_t key(一级索引),所以静态,某个线程退出就析构某个线程特定数据T* 调用ThreadLocalSingleton::destructor,TSD不是要等进程退出了析构deleter时才一次性全部析构线程特定数据,析构deleter时调用pthread_key_delete(key_)只是删除key。
};
template<typename T>
__thread T* ThreadLocalSingleton<T>::t_value_=NULL;

template<typename T>
typename ThreadLocalSingleton<T>::Deleter ThreadLocalSingleton<T>::deleter_;//默认构造函数初始化成员变量ThreadLocalSingleton::deleter_; typename 修饰 ThreadLocalSingleton<T>::Deleter表明 Deleter 是模板中的类型
}

#endif

相关:线程特定数据TSD与__thread

          单例模式

参考:c++教程网

           muduo网络库

           linux多线程服务器端编程》.陈硕


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值