【问题标题】:How does a C++ compiler implement thread local storage in C++0x?C++ 编译器如何在 C++0x 中实现线程本地存储?
【发布时间】:2011-04-13 16:00:19
【问题描述】:

c++编译器如何在C++0x中实现线程本地存储

我在谷歌搜索过这个。但我找不到任何关于此的信息。

有人有这方面的资料吗??

【问题讨论】:

标签: c++ c++11 thread-local thread-local-storage


【解决方案1】:

阅读Wikipedia entry

线程本地存储并不是 C++ 特有的。有时它有不同的名称,例如“TLS”(只是线程本地存储的缩写)或“线程特定存储”(TSS)。

大多数操作系统都提供 API 来访问每个线程的存储。例如,Windows 有一个以“TLS”开头的bunch of API functions。在底层,Win32 为各种每线程数据保留了一个特殊区域,包括用户线程本地存储,可通过特定的 CPU 寄存器(x86 上的 FS)访问。 Linux 通过 pthread API 提供特定于线程的存储,名称类似于 pthread_key_create,这些通常使用类似的技术实现。

操作系统可能根本不提供任何支持。但是,如果操作系统通过 API 提供进程唯一的线程 ID,那么 C++ 运行时库可以在内部维护一些概念上类似于 std::map<thread_id, per_thread_storage> 的东西。当然,那么per_thread_storage 是什么就有问题了。如果一个程序是静态链接的,它可能只是一个指向一个大结构的指针,其中所有在程序中声明为元素的线程局部存储变量。这是一种过于简单化的方法,但您大致了解。

访问线程局部存储变量显然不仅仅是直接的内存读取或写入。它可能比这更复杂。如果您要在特定函数中大量使用线程局部/特定存储,我建议您先将线程局部存储指针复制到局部变量中。

【讨论】:

  • 您已经回答了应用程序开发人员如何实现 TLS,但没有回答编译器和加载器如何处理 C++0x thread_local 关键字
  • @doron:编译器和加载器要么使用操作系统提供的 API,要么自己做一些与映射技术等效的事情,而无需应用程序程序员编写任何代码。
【解决方案2】:

全局变量(或可写静态数据 - WSD)通常存储在与堆栈、堆和代码分开的内存块中。 WSD 块是在可执行文件的代码开始运行之前创建和初始化的。

C++0x 引入了thread_local 关键字,它确保为每个线程创建一个单独的全局变量实例。问题是每个线程需要加载不同的块。

下一个难点是变量的地址在链接时不固定,每个线程都不一样。

有两种方法可以解决这个问题。一种是让编译器生成一个函数调用以获得正确的块,而另一种是更改 ABI 以将 TLS 块存储在一个处理器寄存器中。然后可以将其与偏移量一起使用以访问正确的thread_local 变量。

这与库支持不同,其中操作系统存储单个 void* 值,该值可用于存储指向已在进程堆上分配的线程本地块的指针。

如果您想了解血腥细节,请查看here

【讨论】:

    【解决方案3】:

    您可以使用boost::thread 在不同平台上可移植地处理 TLS。每个的实现都在代码中,应该可以帮助您了解不同的系统如何处理这个区域。

    【讨论】:

    • 在 C++0x 中,编译器确实支持带有 thread_local 关键字的 TLS
    • 使用 boost 没问题,但为了记录,一些编译器确实已经购买了问题空间。 gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Thread-Local.html
    • 和 C++0x 创建了一个新的关键字 thread_local,它的作用与 gcc 的 __thread 完全相同
    猜你喜欢
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    相关资源
    最近更新 更多