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:
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?
So yes, you're safe.
static members and function local variables are not specific to each instance of a class! They are either completely global (one instance per entire executable), or are per-thread if you use C++11 and declare them thread_local . You absolutely need a member variable.
Thread-local storage ( TLS ) is a mechanism by which variables are allocated such that there is one instance of the variable per extant thread. The runtime model GCC uses to implement this originates in the IA-64 processor-specific ABI, but has since been migrated to other processors as well.
The local variables of a function are unique to each thread that runs the function. However, the static and global variables are shared by all threads in the process. With thread local storage (TLS), you can provide unique data for each thread that the process can access using a global index.
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With