能否通过thread_local实现boost::thread_specific_ptr?

6
这个问题可能看起来很奇怪。我想这么做是因为我们有一些代码需要在多个平台上构建,但某些平台不支持thread_local,所以使用boost::thread_specific_ptr代替。然而,为每个平台(x86/x64/arm,debug/release,操作系统等)构建boost二进制文件很麻烦。
我想知道是否可以通过thread_local实现thread_specific_ptr,这样我们就可以让客户端代码更加优雅(避免使用#ifdef)。
我希望有一个头文件,类似于:
#if HAS_THREAD_LOCAL
class thread_specific_ptr
{
    ... // use thread_local to implement
};
#else
using boost::thread_specific_ptr
#endif

我找不到路,也许你可以,谢谢。


1
无论如何,你都无法避免if-defs,我认为最好的方法是采用“boost :: thread_specific_ptr”。“boost :: thread_specific_ptr”提供了一种可移植的线程本地存储机制,适用于Boost.Thread支持的所有编译器。或者,如果您不想构建,则只需复制和转换boost代码(这很痛苦!)。 - Vasiliy Soshnikov
1个回答

3
使用thread_local可以实现thread_specific_ptr。重要的一点是,thread_local是一个存储说明符,而thread_specific_ptr是一个对象。因此,技术上可以动态创建和销毁thread_specific_ptr对象,但是不能对thread_local对象进行这样的操作。例如,您不能将thread_local对象作为类的成员。
但是,thread_local可以被thread_specific_ptr在内部使用,以根据当前线程选择内部结构。该结构可以包含程序中所有thread_specific_ptr的数据,并允许动态创建和删除其元素。例如,可以使用std::map来实现这个目的。
thread_local std::map< void*, std::shared_ptr< void > > thread_specific_ptr_data;

template< typename T >
class thread_specific_ptr
{
public:
    T* get() const
    {
        auto it = thread_specific_ptr_data.find(this);
        if (it != thread_specific_ptr_data.end())
            return static_cast< T* >(it->second.get());
        return nullptr;
    }
};

当然,与原始使用thread_local相比,这会增加一些开销,并且在某些平台上实际上可能比boost::thread_specific_ptr慢一点,因为boost::thread_specific_ptr使用比thread_local更低级的接口。您还需要解决boost::thread_specific_ptr面临的问题,例如使用哪个键在映射中查找值。但是,如果您的目标是消除依赖关系,则此方法可能很有用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接