正如迈克所说
pthread_cleanup_push的不合适。正确的方法是使用
pthread_key_create。
我已经实现了一个小型演示程序,以演示如何执行此操作。我们实现
thread_local您使用的宏,如下所示:
使用真正的C ++ 11功能,它将是:
void f(){ thread_local X x(1,2,3); ...}与此是:
void f(){ thread_local (X, x, 1, 2, 3); ...}与boost ::
thread_specifc_ptr之间的区别是动态内存分配为零。一切都与
__thread持续时间一起存储。它的重量也轻得多,但特定于gcc /
linux。
概述:
- 我们曾经
std::aligned_storage
为变量创建__thread持续时间空间 - 从给定线程的第一个条目开始,我们使用placement new在存储中构造变量
- 我们还
__thread
为展示位置删除调用分配了一个链接列表条目 - 我们
pthread_setspecific
用来跟踪每个线程的列表头 - 传递给该函数的函数
pthread_key_create
会在线程退出时删除调用放置的列表。
…
#include <iostream>#include <thread>using namespace std;static pthread_key_t key;static pthread_once_t once_control = PTHREAD_ONCE_INIT;struct destructor_list{ void (*destructor)(void*); void* param; destructor_list* next;};static void execute_destructor_list(void* v){ for (destructor_list* p = (destructor_list*) v; p != 0; p = p->next) p->destructor(p->param);}static void create_key(){ pthread_key_create(&key, execute_destructor_list);}void add_destructor(destructor_list* p){ pthread_once(&once_control, create_key); p->next = (destructor_list*) pthread_getspecific(key); pthread_setspecific(key, p);}template<class T> static void placement_delete(void* t) { ((T*)t)->~T(); }#define thread_local(T, t, ...) T& t = *((T*) ({ typedef typename aligned_storage<sizeof(T), alignment_of<T>::value>::type Storage; static __thread bool allocated = false; static __thread Storage storage; static __thread destructor_list dlist; if (!allocated) { new (&storage) T(__VA_ARGS__); allocated = true; dlist.destructor = placement_delete<T>; dlist.param = &storage; add_destructor(&dlist); } &storage; }));class X{public: int i; X(int i_in) { i = i_in; cout << "X::X()" << endl; }; void f() { cout << "X::f()" << endl; } ~X() { cout << "X::~X() i = " << i << endl; }};void g(){ thread_local(X, x, 1234); x.f();}int main(){ thread t(g); t.join();}笔记:
- 您需要为每个pthread_ *调用添加错误检查。我只是将其删除以进行说明。
- 它使用
__thread
哪个是GNU扩展 - 它使用 表达式语句 将辅助__thread变量名称保留在父作用域之外。这也是GNU扩展。



