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.
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_ptr
s 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.