c++编译器如何在C++0x中实现线程本地存储
我在谷歌搜索过这个。但我找不到任何关于此的信息。
有人有这方面的资料吗??
c++编译器如何在C++0x中实现线程本地存储
我在谷歌搜索过这个。但我找不到任何关于此的信息。
有人有这方面的资料吗??
阅读Wikipedia 条目。
线程本地存储并不是 C++ 特有的。有时它有不同的名称,例如“TLS”(只是线程本地存储的缩写)或“线程特定存储”(TSS)。
大多数操作系统都提供 API 来访问每个线程的存储。例如,Windows 有一堆以“TLS”开头的 API 函数。在底层,Win32 为各种每线程数据保留了一个特殊区域,包括用户线程本地存储,可通过特定的 CPU 寄存器(x86 上的 FS)访问。Linux 通过 pthread API 提供特定于线程的存储,名称类似于pthread_key_create,这些通常使用类似的技术实现。
操作系统可能根本不提供任何支持。但是,如果操作系统通过 API 提供进程唯一的线程 ID,那么 C++ 运行时库可以在概念上维护一些类似于std::map<thread_id, per_thread_storage>
内部的东西。当然,还有一个问题是什么per_thread_storage
。如果一个程序是静态链接的,它可能只是一个指向一个大结构的指针,其中所有在程序中声明为元素的线程局部存储变量。这是一个过度简化,但你明白了一般的想法。
访问线程局部存储变量显然不仅仅是直接的内存读取或写入。它可能比这更复杂。如果您要在特定函数中大量使用线程局部/特定存储,我建议您首先将线程局部存储指针复制到局部变量中。
全局变量(或可写静态数据 - WSD)通常存储在与堆栈、堆和代码分开的内存块中。WSD 块是在可执行文件的代码开始运行之前创建和初始化的。
C++0x 引入了thread_local
确保每个线程创建一个单独的全局变量实例的关键字。问题是每个线程需要加载不同的块。
下一个难点是变量的地址在链接时不是固定的,每个线程都不一样。
有两种方法可以解决这个问题。一种是让编译器生成一个函数调用以获得正确的块,而另一种是更改 ABI 以将 TLS 块存储在一个处理器寄存器中。然后可以将其与偏移量一起使用以访问正确的thread_local
变量。
这与库支持不同,其中操作系统存储单个void*
值,该值可用于存储指向已在进程堆上分配的线程本地块的指针。
如果你想要血淋淋的细节看这里。
您可以使用boost::thread在不同平台上可移植地处理 TLS。每个的实现都在代码中,应该可以帮助您了解不同的系统如何处理该区域。