pthread 库提供了pthread_key_create, pthread_getspecific, pthread_setspecific方法操作.
原理上提供了一个 <key, pthread_t> ==> T的字典
pthread_getspecific(key) 方法的作用是<key, pthread_self()>查询这个字典, 得到对应的T*, 不同的线程, pthread_self不同, 自然会得到不同的返回值; 同一个线程中如果key不同, 也会得到不同的返回值.
理解了原理, 操作自然简单.
使用C++模板包装一下
#include <pthread.h>
template <class T>
class tls_factory
{
public:
T * create() {
return new T;
}
void destroy(T* t) {
delete t;
}
};
template <class T, class factory_cls=tls_factory<T> >
class ThreadLocal
{
private:
pthread_key_t key;
static void clear_tls(void * t) {
if(t) {
factory_cls factory;
factory.destroy((T*)t);
}
}
public:
ThreadLocal() {
pthread_key_create(&key, clear_tls);
}
T* get() {
void * data = pthread_getspecific(key);
if(data != NULL) {
return (T*)data;
} else {
factory_cls factory;
T * newT = factory.create();
pthread_setspecific(key, newT);
return newT;
}
}
void set(T * newV) {
void * data = pthread_getspecific(key);
if(data != NULL) {
clear_tls(data);
}
pthread_setspecific(newV);
}
T* operator->() {
return get();
}
T& operator*() {
return *get();
}
};
此间有个factory对象, 用来创建和销毁对象, 也可以自定义tls_factory 类作为模板参数传入, 用来定义对象的生成和销毁.
基本测试用例如
typedef struct {
int value;
} AA;
ThreadLocal<AA> locala;
ThreadLocal<AA> localb;
void * __thread_func(void * v) {
locala->value = 700;
localb->value = 800;
cout << "TA " << locala->value << endl;
cout << "TB " << localb.get()->value << endl;
}
void test_threadlocal()
{
pthread_t handle;
locala.get()->value = 100;
localb.get()->value = 200;
pthread_create(&handle, NULL, __thread_func, NULL);
pthread_join(handle, NULL);
cout << "A " << locala.get()->value << endl;
cout << "B " << localb->value << endl;
}
输出
TA 700
TB 800
A 100
B 200