c++ - Linux pthreads 上的 gcc 4.7 - 使用 __thread 的重要 thread_local 解决方法(无提升)

标签 c++ linux multithreading c++11 pthreads

在 C++11 中,您可以拥有一个具有 thread_local 存储的非平凡对象:

class X { ... }

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

不幸的是,此功能尚未在 gcc 中实现(截至 4.7)。

gcc 确实允许您拥有线程局部变量,但仅限于普通类型。

我正在寻找解决方法:

这是我目前所拥有的:

#include <iostream>
#include <type_traits>

using namespace std;

class X
{
public:
    X() { cout << "X::X()" << endl; };
    ~X() { cout << "X::~X()" << endl; }
};

typedef aligned_storage<sizeof(X), alignment_of<X>::value>::type XStorage;

inline void placement_delete_x(X* p) { p->~X(); }

void f()
{
        static __thread bool x_allocated = false;
        static __thread XStorage x_storage;

        if (!x_allocated)
        {
                new (&x_storage) X;
                x_allocated = true;

                // TODO: add thread cleanup that
                //     calls placement_delete_x(&x_storage)
        }

        X& x = *((X*) &x_storage);
}

int main()
{
        f();
}

我需要帮助的是在当前线程退出时调用 placement_delete_x(&x_storage)。我可以使用 pthreads 和/或 linux 中的机制来执行此操作吗?我需要向某种 pthread 清理堆栈添加函数指针和参数吗?

更新:

我认为 pthread_cleanup_push 可能是我想要的:

http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_cleanup_push.3.html

这会在正确的情况下为这种用法调用清理处理程序吗?

更新 2:

看起来 boost::thread_specific_ptr 最终使用 destructor 参数调用了 pthread_key_create,而不是 pthread_cleanup_push -调用它的 tls 清理函数:

http://pubs.opengroup.org/onlinepubs/009696799/functions/pthread_key_create.html

目前尚不清楚这两种方法之间的区别(如果有的话)。 ?

最佳答案

pthread_key_create 和 friend 是您想要使用析构函数实现线程特定类型的变量。但是,这些通常需要您管理创建和销毁变量的整个过程,我不确定您是否可以将它们与 __thread 结合使用。

pthread_cleanup_push 不适合。如果线程在使用该资源的(短)代码块期间退出,它旨在允许释放该资源;如您链接到的文档中所述,它必须与该函数同一级别的 pthread_cleanup_pop 匹配,并且如果线程返回,则不会调用处理程序从它的主要功能。这意味着如果您希望线程局部变量在函数调用之间保持不变,则不能使用它。

为了那些没有禁止第三方库的人的利益,Boost提供了一种方便、可移植的方式来管理线程本地存储。

关于c++ - Linux pthreads 上的 gcc 4.7 - 使用 __thread 的重要 thread_local 解决方法(无提升),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12049684/

相关文章:

linux - 如何为window建立一个基于linux的程序?

C++指针地址解释

android - Android 是否抽象了设备架构?

linux - DC/OS ssh 连接在端口 22 上被拒绝 - 预检

linux - Bash 通过 FOR 重命名

java - 绘制线程

java - 访问同一类中另一个对象的私有(private)字段

c++ - 插入指针列表 C++

multithreading - TCustomClientDataSet CloneCursor 线程安全吗?

java - 为什么这个片段抛出 NullPointerException