问题
I have a class X:
class X { ... }
I want to do this:
void f()
{
thread_local static X x = ...;
...
}
(actually I'm using gcc so keyword is "__thread")
but I can't because you can only have trivial thread_locals.
What is the best work-around for this?
If I do it this way:
void f()
{
thread_local static X* p = 0;
if (!p)
p = new X(...);
X& x = *p;
...
}
then:
- the destructor won't be called when thread exits
- unnecessary dynamic memory allocation.
Update:
Here is what I have so far:
#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();
}
This fixes the dynamic memory allocation problem. I just need to add the thread cleanup handler. Is there a mechanism to do this with pthreads?
回答1:
The Standard describes thread_local
as a storage specifier like the others (static
, extern
etc.) in §7.1.1. There is no restriction to "simple" data types by any definition of that word.
The problem is briefly discussed in a pre-C++11 discussion document N2147 (see the section "Thread Variable Dynamic Initialization"). That includes a description of the key problems involved in the proper implementation. Apparently the GCC implementation (static __thread
) hasn't solved these problems yet (which is consistent with the fact that GCC does not officially support C++11 thread_local
).
One alternative is boost::thread_specfic_ptr<>
mentioned in this earlier post and described here.
Another alternative is to use a std::thread
object to implement the thread and ensure each instance maintains its own copy of the variable, possibly wrapped in a unique_ptr
.
回答2:
thread_local
and __thread
are, in fact, not the same thing. The main difference between them is precisely the one you stumbled upon - thread_local
allows the variable to be non-POD. Unfortunately, this also has performance implications. See this question for more details about those performance implications.
来源:https://stackoverflow.com/questions/12049095/c11-nontrivial-thread-local-static-variable