//
// XXX: Ideally we would instead determine if emutls is in use at runtime as it
// is possible to configure glibc on Linux to use emutls regardless.
-#if !FOLLY_MOBILE && !defined(__APPLE__)
+#if !FOLLY_MOBILE && !defined(__APPLE__) && !defined(_MSC_VER)
#define FOLLY_TLD_USE_FOLLY_TLS 1
#else
#undef FOLLY_TLD_USE_FOLLY_TLS
}
};
- explicit StaticMetaBase(ThreadEntry* (*threadEntry)());
+ StaticMetaBase(ThreadEntry* (*threadEntry)(), bool strict);
- ~StaticMetaBase() {
+ [[noreturn]] ~StaticMetaBase() {
LOG(FATAL) << "StaticMeta lives forever!";
}
uint32_t nextId_;
std::vector<uint32_t> freeIds_;
std::mutex lock_;
+ SharedMutex accessAllThreadsLock_;
pthread_key_t pthreadKey_;
ThreadEntry head_;
ThreadEntry* (*threadEntry_)();
+ bool strict_;
};
// Held in a singleton to track our global instances.
// Creating and destroying ThreadLocalPtr objects, as well as thread exit
// for threads that use ThreadLocalPtr objects collide on a lock inside
// StaticMeta; you can specify multiple Tag types to break that lock.
-template <class Tag>
+template <class Tag, class AccessMode>
struct StaticMeta : StaticMetaBase {
- StaticMeta() : StaticMetaBase(&StaticMeta::getThreadEntrySlow) {
+ StaticMeta()
+ : StaticMetaBase(
+ &StaticMeta::getThreadEntrySlow,
+ std::is_same<AccessMode, AccessModeStrict>::value) {
registerAtFork(
/*prepare*/ &StaticMeta::preFork,
/*parent*/ &StaticMeta::onForkParent,
/*child*/ &StaticMeta::onForkChild);
}
- static StaticMeta<Tag>& instance() {
+ static StaticMeta<Tag, AccessMode>& instance() {
// Leak it on exit, there's only one per process and we don't have to
// worry about synchronization with exiting threads.
- static auto instance = detail::createGlobal<StaticMeta<Tag>, void>();
+ /* library-local */ static auto instance =
+ detail::createGlobal<StaticMeta<Tag, AccessMode>, void>();
return *instance;
}