// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "util/thread_local.h"
-#include "util/mutexlock.h"
-#include "port/likely.h"
+
#include <stdlib.h>
+#include "port/likely.h"
+#include "util/mutexlock.h"
+
namespace ROCKSDB_NAMESPACE {
struct Entry {
// ---------------------------------------------------
struct ThreadData {
explicit ThreadData(ThreadLocalPtr::StaticMeta* _inst)
- : entries(),
- next(nullptr),
- prev(nullptr),
- inst(_inst) {}
+ : entries(), next(nullptr), prev(nullptr), inst(_inst) {}
std::vector<Entry> entries;
ThreadData* next;
ThreadData* prev;
};
class ThreadLocalPtr::StaticMeta {
-public:
+ public:
StaticMeta();
// Return the next available Id
// should be used. One example is OnThreadExit() function.
port::Mutex* MemberMutex() { return &mutex_; }
-private:
+ private:
// Get UnrefHandler for id with acquiring mutex
// REQUIRES: mutex locked
UnrefHandler GetHandler(uint32_t id);
// The private mutex. Developers should always use Mutex() instead of
// using this variable directly.
port::Mutex mutex_;
-#ifdef ROCKSDB_SUPPORT_THREAD_LOCAL
// Thread local storage
- static __thread ThreadData* tls_;
-#endif
+ static thread_local ThreadData* tls_;
// Used to make thread exit trigger possible if !defined(OS_MACOSX).
// Otherwise, used to retrieve thread data.
pthread_key_t pthread_key_;
};
-
-#ifdef ROCKSDB_SUPPORT_THREAD_LOCAL
-__thread ThreadData* ThreadLocalPtr::StaticMeta::tls_ = nullptr;
-#endif
+thread_local ThreadData* ThreadLocalPtr::StaticMeta::tls_ = nullptr;
// Windows doesn't support a per-thread destructor with its
// TLS primitives. So, we build it manually by inserting a
// This is set to OnThreadExit in StaticMeta singleton constructor
UnrefHandler thread_local_inclass_routine = nullptr;
-pthread_key_t thread_local_key = pthread_key_t (-1);
+pthread_key_t thread_local_key = pthread_key_t(-1);
// Static callback function to call with each thread termination.
void NTAPI WinOnThreadExit(PVOID module, DWORD reason, PVOID reserved) {
}
}
-} // wintlscleanup
+} // namespace wintlscleanup
// extern "C" suppresses C++ name mangling so we know the symbol name for the
// linker /INCLUDE:symbol pragma above.
// the following variable will go first, then OnThreadExit, therefore causing
// invalid access.
//
- // The above problem can be solved by using thread_local to store tls_ instead
- // of using __thread. The major difference between thread_local and __thread
- // is that thread_local supports dynamic construction and destruction of
+ // The above problem can be solved by using thread_local to store tls_.
+ // thread_local supports dynamic construction and destruction of
// non-primitive typed variables. As a result, we can guarantee the
// destruction order even when the main thread dies before any child threads.
- // However, thread_local is not supported in all compilers that accept -std=c++11
- // (e.g., eg Mac with XCode < 8. XCode 8+ supports thread_local).
static ThreadLocalPtr::StaticMeta* inst = new ThreadLocalPtr::StaticMeta();
return inst;
}
}
ThreadLocalPtr::StaticMeta::StaticMeta()
- : next_instance_id_(0),
- head_(this),
- pthread_key_(0) {
+ : next_instance_id_(0), head_(this), pthread_key_(0) {
if (pthread_key_create(&pthread_key_, &OnThreadExit) != 0) {
abort();
}
#if !defined(OS_WIN)
static struct A {
~A() {
-#ifndef ROCKSDB_SUPPORT_THREAD_LOCAL
- ThreadData* tls_ =
- static_cast<ThreadData*>(pthread_getspecific(Instance()->pthread_key_));
-#endif
if (tls_) {
OnThreadExit(tls_);
}
head_.prev = d;
}
-void ThreadLocalPtr::StaticMeta::RemoveThreadData(
- ThreadData* d) {
+void ThreadLocalPtr::StaticMeta::RemoveThreadData(ThreadData* d) {
Mutex()->AssertHeld();
d->next->prev = d->prev;
d->prev->next = d->next;
}
ThreadData* ThreadLocalPtr::StaticMeta::GetThreadLocal() {
-#ifndef ROCKSDB_SUPPORT_THREAD_LOCAL
- // Make this local variable name look like a member variable so that we
- // can share all the code below
- ThreadData* tls_ =
- static_cast<ThreadData*>(pthread_getspecific(Instance()->pthread_key_));
-#endif
-
if (UNLIKELY(tls_ == nullptr)) {
auto* inst = Instance();
tls_ = new ThreadData(inst);
}
bool ThreadLocalPtr::StaticMeta::CompareAndSwap(uint32_t id, void* ptr,
- void*& expected) {
+ void*& expected) {
auto* tls = GetThreadLocal();
if (UNLIKELY(id >= tls->entries.size())) {
// Need mutex to protect entries access within ReclaimId
}
void ThreadLocalPtr::StaticMeta::Scrape(uint32_t id, autovector<void*>* ptrs,
- void* const replacement) {
+ void* const replacement) {
MutexLock l(Mutex());
for (ThreadData* t = head_.next; t != &head_; t = t->next) {
if (id < t->entries.size()) {
}
}
-uint32_t ThreadLocalPtr::TEST_PeekId() {
- return Instance()->PeekId();
-}
+uint32_t ThreadLocalPtr::TEST_PeekId() { return Instance()->PeekId(); }
void ThreadLocalPtr::StaticMeta::SetHandler(uint32_t id, UnrefHandler handler) {
MutexLock l(Mutex());
}
}
-ThreadLocalPtr::~ThreadLocalPtr() {
- Instance()->ReclaimId(id_);
-}
+ThreadLocalPtr::~ThreadLocalPtr() { Instance()->ReclaimId(id_); }
-void* ThreadLocalPtr::Get() const {
- return Instance()->Get(id_);
-}
+void* ThreadLocalPtr::Get() const { return Instance()->Get(id_); }
-void ThreadLocalPtr::Reset(void* ptr) {
- Instance()->Reset(id_, ptr);
-}
+void ThreadLocalPtr::Reset(void* ptr) { Instance()->Reset(id_, ptr); }
-void* ThreadLocalPtr::Swap(void* ptr) {
- return Instance()->Swap(id_, ptr);
-}
+void* ThreadLocalPtr::Swap(void* ptr) { return Instance()->Swap(id_, ptr); }
bool ThreadLocalPtr::CompareAndSwap(void* ptr, void*& expected) {
return Instance()->CompareAndSwap(id_, ptr, expected);