问题
c++ 11引入了thread_local
,它提供线程本地数据,但不能与非静态数据成员一起使用。
这导致了一个问题:
Why may thread_local not be applied to non-static data members and how to implement thread-local non-static data members?
答案是:
但是 boost::thread_specific_ptr
析构函数附加了以下note:
有办法解决这个问题吗?
我需要为非静态数据成员提供线程本地存储,这将在销毁时释放所有线程数据,即使仍有线程正在运行(或至少销毁时不会失败/泄漏的tls)。
如果 boost::thread_specific_ptr
不是正确的选择,我可以改用互斥保护的std::vector
吗?
背景
我有一个线程安全的类,该类从mongodb接收数据。
class JsonTable
{
public:
std::string getData() const;
//....
private:
ThreadLocalStorage<mongocxx::client> _clients;
//....
};
mongocxx::client
不得在多个线程之间共享。因此,为了使
getData
成为线程安全的,我需要为每个线程构造一个mongocxx::client
。当我的JsonTable
类被销毁时,我希望所有客户端都被关闭/销毁,即使最初创建它们的线程仍在运行。 最佳答案
将线程本地静态映射从ptr-to-this映射到shared-ptr到wrapper-ptr to-data的包装器。
创建一个共享列表到数据的非静态同步列表。
根据需要填充线程本地映射。填充后,将其添加到实例列表。
在销毁对象时,使用原子共享的ptr操作从列表的所有元素中清除内部的shared_ptr。这将删除线程本地每个实例的数据。
双重共享ptr周围的包装器还使用原子操作清除内部共享ptr。如果线程死亡,这将清除数据。
实例和线程都共享一个共享的ptr(内部线程),其生命周期由外部的共享ptr管理(因此,当线程和实例都消失时,它就会死掉)。
唯一的同步发生在对象被破坏或新线程访问该对象时,这应保持稳定的性能。
映射条目(具有空数据)比实例持久。如果需要,您可以花点时间定期清理它们。如果您有许多 transient 实例与许多持久线程进行交互,则可能会出现问题。添加一个使用中的数据与清除的数据的原子计数器,当计数器变高时,在添加新条目时进行一次删除清除的条目的操作。
关于c++ - 非静态数据成员的thread_local数据,再一次,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38459938/