C++ 11:非平凡线程局部静态变量?

And*_*zos 9 c++ multithreading thread-local thread-local-storage c++11

我有一个班级X:

class X { ... }
Run Code Online (Sandbox Code Playgroud)

我想做这个:

void f()
{
    thread_local static X x = ...;

    ...
}
Run Code Online (Sandbox Code Playgroud)

(实际上我正在使用gcc所以关键字是"__thread")

但我不能,因为你只能有琐碎的thread_locals.

最好的解决办法是什么?

如果我这样做:

void f()
{
    thread_local static X* p = 0;

    if (!p)
       p = new X(...);

    X& x = *p;

    ...
}
Run Code Online (Sandbox Code Playgroud)

然后:

  1. 线程退出时不会调用析构函数
  2. 不必要的动态内存分配

更新:

这是我到目前为止:

#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();
}
Run Code Online (Sandbox Code Playgroud)

这解决了动态内存分配问题.我只需要添加线程清理处理程序.有没有机制用pthreads做到这一点?

jog*_*pan 6

该标准描述thread_local为其他类似的存储说明符(static,extern在第7.1.1节等).通过该单词的任何定义,对"简单"数据类型没有限制.

在前C++ 11讨论文档N2147中简要讨论了该问题(参见"线程变量动态初始化"一节).这包括对正确实施中涉及的关键问题的描述.显然,GCC实现(static __thread)尚未解决这些问题(这与GCC不正式支持C++ 11的事实一致thread_local).

一种替代方法是boost::thread_specfic_ptr<>提到在这个早期的岗位和描述在这里.

另一种方法是使用一个std::thread对象来实现线程,并确保每个实例都维护自己的变量副本,可能包含在一个变量中unique_ptr.


Sha*_*esh 6

thread_local并且__thread,事实上,不是一回事.它们之间的主要区别正是您偶然发现的 - thread_local允许变量为非POD.不幸的是,这也有性能影响.有关这些性能影响的更多详细信息,请参阅此问题