Commit 36ca8450 authored by Hans Fugal's avatar Hans Fugal Committed by Sara Golemon

Replace thread_local with FOLLY_TLS

Summary: OSX doesn't support C++11's `thread_local`. :-/ (yet? http://stackoverflow.com/questions/28094794/why-does-apple-clang-disallow-c11-thread-local-when-official-clang-supports/29929949#29929949)
We have `FOLLY_TLS` in `Portability.h` https://github.com/facebook/folly/blob/master/folly/Portability.h#L163-L175

So replace the usages of `thread_local` with `FOLLY_TLS`. But `__thread` is not drop-in compatible with `thread_local`, specifically the former requires global storage and needs a constexpr initializer, and a trivial destructor.

`futures/QueuedImmediateExecutor` now uses `folly::ThreadLocal` (because `std::queue` has a non-trivial destructor). It might end up in one more alloc, per thread. I also rearranged the code to clarify the fact that although there may be many `QueuedImmediateExecutor`s, they all share the same queue per thread.

I didn't use `folly::ThreadLocal` for fibers, because I thought it might be too expensive. But now I'm not so sure. I had to do the "check for default and then initialize" thing because of the requirement for constexpr initialization for `__thread` (and therefore `FOLLY_TLS`).

Reviewed By: @jsedgwick

Differential Revision: D2140369
parent bb400ba0
...@@ -34,7 +34,12 @@ namespace { ...@@ -34,7 +34,12 @@ namespace {
static const uint64_t kMagic8Bytes = 0xfaceb00cfaceb00c; static const uint64_t kMagic8Bytes = 0xfaceb00cfaceb00c;
pid_t localThreadId() { pid_t localThreadId() {
static thread_local pid_t threadId = syscall(SYS_gettid); // __thread doesn't allow non-const initialization.
// OSX doesn't support thread_local.
static FOLLY_TLS pid_t threadId = 0;
if (UNLIKELY(threadId == 0)) {
threadId = syscall(SYS_gettid);
}
return threadId; return threadId;
} }
......
...@@ -18,15 +18,16 @@ ...@@ -18,15 +18,16 @@
#include <cassert> #include <cassert>
#include <folly/CPortability.h> #include <folly/CPortability.h>
#include <folly/Memory.h>
#include <folly/Optional.h>
#include <folly/Portability.h>
#include <folly/ScopeGuard.h>
#include <folly/ThreadLocal.h>
#include <folly/experimental/fibers/Baton.h> #include <folly/experimental/fibers/Baton.h>
#include <folly/experimental/fibers/Fiber.h> #include <folly/experimental/fibers/Fiber.h>
#include <folly/experimental/fibers/LoopController.h> #include <folly/experimental/fibers/LoopController.h>
#include <folly/experimental/fibers/Promise.h> #include <folly/experimental/fibers/Promise.h>
#include <folly/futures/Try.h> #include <folly/futures/Try.h>
#include <folly/Memory.h>
#include <folly/Optional.h>
#include <folly/Portability.h>
#include <folly/ScopeGuard.h>
namespace folly { namespace fibers { namespace folly { namespace fibers {
...@@ -454,8 +455,8 @@ T& FiberManager::local() { ...@@ -454,8 +455,8 @@ T& FiberManager::local() {
template <typename T> template <typename T>
T& FiberManager::localThread() { T& FiberManager::localThread() {
static thread_local T t; static ThreadLocal<T> t;
return t; return *t;
} }
inline void FiberManager::initLocalData(Fiber& fiber) { inline void FiberManager::initLocalData(Fiber& fiber) {
......
...@@ -20,17 +20,17 @@ ...@@ -20,17 +20,17 @@
namespace folly { namespace folly {
void QueuedImmediateExecutor::add(Func callback) { void QueuedImmediateExecutor::addStatic(Func callback) {
thread_local std::queue<Func> q; static folly::ThreadLocal<std::queue<Func>> q_;
if (q.empty()) { if (q_->empty()) {
q.push(std::move(callback)); q_->push(std::move(callback));
while (!q.empty()) { while (!q_->empty()) {
q.front()(); q_->front()();
q.pop(); q_->pop();
} }
} else { } else {
q.push(callback); q_->push(callback);
} }
} }
......
...@@ -27,7 +27,13 @@ namespace folly { ...@@ -27,7 +27,13 @@ namespace folly {
*/ */
class QueuedImmediateExecutor : public Executor { class QueuedImmediateExecutor : public Executor {
public: public:
void add(Func) override; /// There's really only one queue per thread, no matter how many
/// QueuedImmediateExecutor objects you may have.
static void addStatic(Func);
void add(Func func) override {
addStatic(std::move(func));
}
}; };
} // folly } // folly
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment