diff --git a/src/object-store/src/util/thread_id.hpp b/src/object-store/src/util/thread_id.hpp index e1121e2a..fc76a328 100644 --- a/src/object-store/src/util/thread_id.hpp +++ b/src/object-store/src/util/thread_id.hpp @@ -23,17 +23,73 @@ #include +#if __has_feature(tls) || __has_feature(cxx_thread_local) +#define REALM_HAS_THREAD_LOCAL 1 +#else +#define REALM_HAS_THREAD_LOCAL 0 +#include +#endif + namespace realm { using thread_id_t = std::size_t; +namespace _impl { + +#if !REALM_HAS_THREAD_LOCAL +template +class ThreadLocal { + public: + ThreadLocal() : m_initial_value() { + init_key(); + } + ThreadLocal(const T &value) : m_initial_value(value) { + init_key(); + } + ~ThreadLocal() { + pthread_key_delete(m_key); + } + + operator T&() { + void* ptr = pthread_getspecific(m_key); + if (!ptr) { + ptr = new T(m_initial_value); + pthread_setspecific(m_key, ptr); + } + return *static_cast(ptr); + } + T& operator=(const T &value) { + T& value_ref = operator T&(); + value_ref = value; + return value_ref; + } + + private: + T m_initial_value; + pthread_key_t m_key; + + void init_key() { + pthread_key_create(&m_key, [](void* ptr) { + delete static_cast(ptr); + }); + } +}; +#endif + +} // namespace _impl + namespace util { // Since std::thread::id may be reused after a thread is destroyed, we use // an atomically incremented, thread-local identifier instead. inline thread_id_t get_thread_id() { static std::atomic id_counter; + +#if REALM_HAS_THREAD_LOCAL static REALM_THREAD_LOCAL thread_id_t thread_id = 0; +#else + static _impl::ThreadLocal thread_id = 0; +#endif if (REALM_UNLIKELY(!thread_id)) { thread_id = ++id_counter;