thread_local 非静态数据成员的数据,再一次

thread_local data for non static data members, once more

问题

c++11引入了thread_local,它提供了线程本地数据,但不能与非静态数据成员一起使用。

由此引出问题:

答案:

... I suggest using boost::thread_specific_ptr. You can put one of these inside your class and get the behavior you want.

但是boost::thread_specific_ptr destructor has the following note附上:

All the thread specific instances associated to this thread_specific_ptr (except maybe the one associated to this thread) must be null.

有办法解决这个问题吗?
我需要非静态数据成员的线程本地存储,这将在销毁时释放所有线程数据,即使仍有线程 运行 (或至少在销毁时没有 fail/leak 的 tls ).
如果 boost::thread_specific_ptr 不是正确的选择,我可以使用互斥保护 std::vector 代替吗?


背景

我有一个 threadsafe class 从 mongodb.

接收数据
class JsonTable
{
    public:
    std::string getData() const;
    //....
    private:
    ThreadLocalStorage<mongocxx::client> _clients;
    //....
};

mongocxx::client 不得跨多个线程共享。 因此,为了使 getData 线程安全,我需要为每个线程构造一个 mongocxx::client。当我的 JsonTable class 被破坏时,我希望所有客户端都是 closed/destructed 即使最初创建它们的线程仍然是 运行.

创建一个从 ptr-to-this 到围绕 shared-ptr 到 shared-ptr 到数据的包装器的线程本地静态映射。

创建共享指针到共享指针到数据的非静态同步列表。

按需填充线程本地映射。填充后,将其添加到实例列表中。

在对象销毁时,使用原子共享 ptr 操作从列表的所有元素中清除内部 shared_ptr。这将删除线程局部实例数据。

双共享指针的包装器也使用原子操作来清除内部共享指针。如果线程死亡,这将清除数据。

实例和线程一起共享一个共享指针(内部),其生命周期由外部共享指针管理(因此当线程和实例都消失时它会死亡)。

唯一的同步发生在对象被销毁或新线程访问对象时,这应该能保持稳定的性能;

映射条目(带有空数据)比实例更持久。如果需要,您可以花一些时间以某种方式定期清理它们。如果您有许多瞬态实例与许多持久线程相互作用,则可能会出现问题。添加一个使用中数据与已清除数据的原子计数器,当它变高时,在添加新条目时通过删除已清除条目。