我正在编写一个 C++11 类 Foo,我想为每个实例提供自己的 Bar 类型的线程本地存储。也就是说,我希望每个线程和每个 Foo 实例分配一个 Bar。
如果我使用 pthreads,Foo 将有一个类型为 pthread_key_t 的非静态成员,Foo 的构造函数将使用 pthread_key_create() 进行初始化,而 Foo 的析构函数将使用 pthread_key_delete() 释放。或者,如果我只为 Microsoft Windows 编写代码,我可以用 TlsAlloc() 和 TlsFree() 做类似的事情。或者,如果我使用 Boost.Thread,Foo 将有一个 boost::thread_specific_ptr 类型的非静态成员。
然而,实际上,我正在尝试编写可移植的 C++11。 C++11 thread_local
关键字不适用于非静态数据成员。因此,如果您希望每个线程有一个 Bar 很好,但如果您希望每个 Foo 每个线程有一个 Bar,那就不行了。
因此,据我所知,我需要定义一个从 Foos 到 Bars 的线程本地映射,然后处理如何在 Foo 被销毁时进行适当清理的问题。但在我开始之前,我在这里发帖是希望有人能阻止我说“有一种更简单的方法”。
(顺便说一句,我不使用 pthread_key_create() 或 boost::thread_specific_ptr 的原因是,如果我理解正确,他们假设所有线程都将分别使用 pthreads 或 Boost.Thread 产生。我不想让关于我的代码的用户将如何产生线程的任何假设。)
最佳答案
你要 Foo
包含 thread_local
类型变量 Bar
.如前所述,因为 thread_local
不能应用于数据成员,我们必须做一些更间接的事情。底层行为将针对 Bar
的 N 个实例。存在于 Foo
的每个实例中,其中 N 是存在的线程数。
这是一种效率低下的方法。有了更多的代码,它可以做得更快。基本上,每个 Foo 将包含一个 TLS 映射。
#include <unordered_map>
class Bar { ... };
class Foo {
private:
static thread_local std::unordered_map<Foo*, Bar> tls;
public:
// All internal member functions must use this too.
Bar *get_bar() {
auto I = tls.find(this);
if (I != tls.end())
return &I->second;
auto II = tls.emplace(this, Bar()); // Could use std::piecewise_construct here...
return &II->second.second;
}
};
关于multithreading - C++11 中的动态 TLS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22446534/