muduo库-ThreadLocalSingleton类

muduo库-ThreadLocalSingleton类

ThreadLocalSingleton类图如下:

ThreadLocalSingleton 类封装为了线程本地存储单例类。在 Signleton 中提到过,常见的单例模式设计分为四种:

  • 懒汉式
  • 双检锁
  • 饿汉式
  • 局部静态式

ThreadLocalSingleton 类则采用了懒汉式的构建方法,而且由于是线程本地存储,则无需互斥锁来保证线程安全:

1
2
3
4
5
6
7
static T& instance() {
if (!t_value_) {
t_value_ = new T();
deleter_.set(t_value_);
}
return *t_value_;
}

ThreadLocalSignleton 类有两个成员变量:

1
2
static __thread T* t_value_;
static Deleter deleter_;

其中,t_value_ 用于构建单例对象,由于 T* 为指针类型,即 POD 类型,因此可以使用 __thread 关键字进行修饰,使其成为线程本地存储数据,而无需使用 ThreadLocal 类型。其次,deleter_ 变量则用于声明一个 Deleter 类对象,该类用于销毁 t_value_所指的对象,其定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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_;
};

可见,Deleter 是一个 TSD(Thread Specific Data) 类型,只为线程本地所拥有。类似于 ThreadLocal 类型,它使用 RAII 方式,在构造函数中创建 key,以绑定 ThreadLocalSingleton 类中的销毁函数,而在析构函数中则删除 key

销毁对象的函数则如下:

1
2
3
4
5
6
7
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 dummy; (void) dummy;
delete t_value_;
t_value_ = 0;
}

同样的,首先判断类型 T 是否为不完全类型,如果是,则会在编译期发生错误,否则可以调用 delete 以调用析构函数,销毁该对象。

总结

ThreadLocalSingleton 类的结构图如下:

参考:


muduo库-ThreadLocalSingleton类
https://gstarmin.github.io/2023/06/28/muduo库-ThreadLocalSingleton类/
作者
Starmin
发布于
2023年6月28日
许可协议