Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to implement boost::thread_specific_ptr via thread_local?

This problem may looks strange. I want to do that because we have some code need to be built on several platforms, but some platform doesn't support thread_local, then use boost::thread_specific_ptr instead. however, it's unpleasing to build boost binary for every platform (x86/x64/arm, debug/release, os, too many).

I wonder if it's possible to imp thread_specific_ptr via thread_local so that we can keep client code more elegant(avoid #ifdef)

I want to have a header file like:

#if HAS_THREAD_LOCAL
class thread_specific_ptr
{
    ... // use thread_local to implement
};
#else
using boost::thread_specific_ptr
#endif

I can't find the way, maybe you can, thanks.

like image 626
P.X Avatar asked Oct 30 '22 06:10

P.X


1 Answers

It is possible to implement thread_specific_ptr using thread_local. The important part one has to remember is that thread_local is a storage specifier and thread_specific_ptr is an object. As such it's technically possible to dynamically create and destroy thread_specific_ptr objects while you cannot do that with thread_local objects. For instance, you cannot put a thread_local object as a member of your class.

However, thread_local can be used internally by thread_specific_ptr to select an internal structure based on the current thread. That structure can contain data for all thread_specific_ptrs in the program, and allow dynamic creation and deletion of its elements. One could use a std::map for this purpose, for example.

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;
    }
};

That, of course, adds some overhead compared to the raw use of thread_local, and it can actually be a bit slower than boost::thread_specific_ptr on some platforms because boost::thread_specific_ptr uses lower-level interfaces than thread_local. You would also have to solve the problems boost::thread_specific_ptr is facing, like what key to use to look for the value in the map. But this approach can be useful if your goal is to remove the dependency.

like image 189
Andrey Semashev Avatar answered Nov 04 '22 07:11

Andrey Semashev