| #pragma once |
| |
| #include <c10/macros/Macros.h> |
| |
| /** |
| * Android versions with libgnustl incorrectly handle thread_local C++ |
| * qualifier with composite types. NDK up to r17 version is affected. |
| * |
| * (A fix landed on Jun 4 2018: |
| * https://android-review.googlesource.com/c/toolchain/gcc/+/683601) |
| * |
| * In such cases, use c10::ThreadLocal<T> wrapper |
| * which is `pthread_*` based with smart pointer semantics. |
| * |
| * In addition, convenient macro C10_DEFINE_TLS_static is available. |
| * To define static TLS variable of type std::string, do the following |
| * ``` |
| * C10_DEFINE_TLS_static(std::string, str_tls_); |
| * /////// |
| * { |
| * *str_tls_ = "abc"; |
| * assert(str_tls_->length(), 3); |
| * } |
| * ``` |
| * |
| * (see c10/test/util/ThreadLocal_test.cpp for more examples) |
| */ |
| #if !defined(C10_PREFER_CUSTOM_THREAD_LOCAL_STORAGE) |
| |
| #if defined(C10_ANDROID) && defined(__GLIBCXX__) && __GLIBCXX__ < 20180604 |
| #define C10_PREFER_CUSTOM_THREAD_LOCAL_STORAGE |
| #endif // defined(C10_ANDROID) && defined(__GLIBCXX__) && __GLIBCXX__ < 20180604 |
| |
| #endif // !defined(C10_PREFER_CUSTOM_THREAD_LOCAL_STORAGE) |
| |
| #if defined(C10_PREFER_CUSTOM_THREAD_LOCAL_STORAGE) |
| #include <c10/util/Exception.h> |
| #include <errno.h> |
| #include <pthread.h> |
| #include <memory> |
| namespace c10 { |
| |
| /** |
| * @brief Temporary thread_local C++ qualifier replacement for Android |
| * based on `pthread_*`. |
| * To be used with composite types that provide default ctor. |
| */ |
| template <typename Type> |
| class ThreadLocal { |
| public: |
| ThreadLocal() { |
| pthread_key_create( |
| &key_, [](void* buf) { delete static_cast<Type*>(buf); }); |
| } |
| |
| ~ThreadLocal() { |
| if (void* current = pthread_getspecific(key_)) { |
| delete static_cast<Type*>(current); |
| } |
| |
| pthread_key_delete(key_); |
| } |
| |
| ThreadLocal(const ThreadLocal&) = delete; |
| ThreadLocal& operator=(const ThreadLocal&) = delete; |
| |
| Type& get() { |
| if (void* current = pthread_getspecific(key_)) { |
| return *static_cast<Type*>(current); |
| } |
| |
| std::unique_ptr<Type> ptr = std::make_unique<Type>(); |
| if (0 == pthread_setspecific(key_, ptr.get())) { |
| return *ptr.release(); |
| } |
| |
| int err = errno; |
| TORCH_INTERNAL_ASSERT(false, "pthread_setspecific() failed, errno = ", err); |
| } |
| |
| Type& operator*() { |
| return get(); |
| } |
| |
| Type* operator->() { |
| return &get(); |
| } |
| |
| private: |
| pthread_key_t key_; |
| }; |
| |
| } // namespace c10 |
| |
| #define C10_DEFINE_TLS_static(Type, Name) static ::c10::ThreadLocal<Type> Name |
| |
| #define C10_DECLARE_TLS_class_static(Class, Type, Name) \ |
| static ::c10::ThreadLocal<Type> Name |
| |
| #define C10_DEFINE_TLS_class_static(Class, Type, Name) \ |
| ::c10::ThreadLocal<Type> Class::Name |
| |
| #else // defined(C10_PREFER_CUSTOM_THREAD_LOCAL_STORAGE) |
| |
| namespace c10 { |
| |
| /** |
| * @brief Default thread_local implementation for non-Android cases. |
| * To be used with composite types that provide default ctor. |
| */ |
| template <typename Type> |
| class ThreadLocal { |
| public: |
| using Accessor = Type* (*)(); |
| explicit ThreadLocal(Accessor accessor) : accessor_(accessor) {} |
| |
| ThreadLocal(const ThreadLocal&) = delete; |
| ThreadLocal& operator=(const ThreadLocal&) = delete; |
| |
| Type& get() { |
| return *accessor_(); |
| } |
| |
| Type& operator*() { |
| return get(); |
| } |
| |
| Type* operator->() { |
| return &get(); |
| } |
| |
| private: |
| Accessor accessor_; |
| }; |
| |
| } // namespace c10 |
| |
| #define C10_DEFINE_TLS_static(Type, Name) \ |
| static ::c10::ThreadLocal<Type> Name([]() { \ |
| static thread_local Type var; \ |
| return &var; \ |
| }) |
| |
| #define C10_DECLARE_TLS_class_static(Class, Type, Name) \ |
| static ::c10::ThreadLocal<Type> Name |
| |
| #define C10_DEFINE_TLS_class_static(Class, Type, Name) \ |
| ::c10::ThreadLocal<Type> Class::Name([]() { \ |
| static thread_local Type var; \ |
| return &var; \ |
| }) |
| |
| #endif // defined(C10_PREFER_CUSTOM_THREAD_LOCAL_STORAGE) |