C++11: Nontrivial Thread Local Static Variable?

笑着哭i 提交于 2020-01-01 08:46:21

问题


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?


回答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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!