9

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:

  1. the destructor won't be called when thread exits
  2. 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?

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319

2 Answers2

6

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.

Community
  • 1
  • 1
jogojapan
  • 68,383
  • 11
  • 101
  • 131
  • I need to change my question slightly (maybe need to post new one). Using boost or std::thread is not an option in my environment. I have got the dynamic allocation problem fixed (see my update), however I still need a way to call the destructor on thread exit. Is there a way to do this with pthreads? (I realize this is now a gcc specific question) – Andrew Tomazos Aug 21 '12 at 06:33
  • 1
    I'll post new question, it's easier. – Andrew Tomazos Aug 21 '12 at 06:40
  • http://stackoverflow.com/questions/12049684/gcc-4-7-on-linux-pthreads-nontrivial-thread-local-workaround-using-thread-n – Andrew Tomazos Aug 21 '12 at 06:53
6

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.

Community
  • 1
  • 1
Shachar Shemesh
  • 8,193
  • 6
  • 25
  • 57