Emulate thread_local for older iPhone targets

It seems that Xcode clang will not even support __thread for iPhone 5 and older, so this includes a simple abstraction over pthread keys in that case.
This commit is contained in:
Scott Kyle 2016-06-09 10:38:49 -07:00
parent 446cb0245e
commit b55483d2d9
1 changed files with 56 additions and 0 deletions

View File

@ -23,17 +23,73 @@
#include <atomic> #include <atomic>
#if __has_feature(tls) || __has_feature(cxx_thread_local)
#define REALM_HAS_THREAD_LOCAL 1
#else
#define REALM_HAS_THREAD_LOCAL 0
#include <pthread.h>
#endif
namespace realm { namespace realm {
using thread_id_t = std::size_t; using thread_id_t = std::size_t;
namespace _impl {
#if !REALM_HAS_THREAD_LOCAL
template<typename T>
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<T*>(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<T*>(ptr);
});
}
};
#endif
} // namespace _impl
namespace util { namespace util {
// Since std::thread::id may be reused after a thread is destroyed, we use // Since std::thread::id may be reused after a thread is destroyed, we use
// an atomically incremented, thread-local identifier instead. // an atomically incremented, thread-local identifier instead.
inline thread_id_t get_thread_id() { inline thread_id_t get_thread_id() {
static std::atomic<thread_id_t> id_counter; static std::atomic<thread_id_t> id_counter;
#if REALM_HAS_THREAD_LOCAL
static REALM_THREAD_LOCAL thread_id_t thread_id = 0; static REALM_THREAD_LOCAL thread_id_t thread_id = 0;
#else
static _impl::ThreadLocal<thread_id_t> thread_id = 0;
#endif
if (REALM_UNLIKELY(!thread_id)) { if (REALM_UNLIKELY(!thread_id)) {
thread_id = ++id_counter; thread_id = ++id_counter;