我有一个班级X:
class X { ... }
我想这样做:
void f()
{
thread_local static X x = ...;
...
}
(实际上我正在使用gcc,因此关键字是“__thread”)
但我不能,因为你只能有琐碎的thread_locals。
最好的解决办法是什么?
如果我这样做:
void f()
{
thread_local static X* p = 0;
if (!p)
p = new X(...);
X& x = *p;
...
}
然后:
更新
这是我到目前为止所做的:
#include <iostream>
#include <type_traits>
using namespace std;
class X { public: X() { cout << "X::X()" << endl; }; ~X() { cout << "X::~X()" << endl; } };
void f()
{
static __thread bool x_allocated = false;
static __thread aligned_storage<sizeof(X),
alignment_of<X>::value>::type x_storage;
if (!x_allocated)
{
new (&x_storage) X;
x_allocated = true;
// add thread cleanup that calls destructor
}
X& x = *((X*) &x_storage);
}
int main()
{
f();
}
这解决了动态内存分配问题。我只需要添加线程清理处理程序。有没有机制用pthreads做到这一点?
答案 0 :(得分:6)
标准将thread_local
描述为与第7.1.1节中的其他(static
,extern
等)一样的存储说明符。通过该单词的任何定义,对“简单”数据类型没有限制。
在pre-C++11 discussion document N2147中简要讨论了该问题(参见“线程变量动态初始化”一节)。这包括对正确实施中涉及的关键问题的描述。显然GCC实现(static __thread
)还没有解决这些问题(这与GCC没有正式支持C ++ 11 thread_local
)这一事实是一致的。
另一种选择是boost::thread_specfic_ptr<>
提及in this earlier post并描述here。
另一种方法是使用std::thread
对象来实现线程,并确保每个实例都维护自己的变量副本,可能包含在unique_ptr
中。
答案 1 :(得分:6)
thread_local
和__thread
并不是一回事。它们之间的主要区别正是您偶然发现的那个 - thread_local
允许变量为非POD。不幸的是,这也有性能影响。有关这些性能影响的详细信息,请参阅this question。