Replace thread_local with FOLLY_TLS
authorHans Fugal <fugalh@fb.com>
Thu, 11 Jun 2015 20:53:21 +0000 (13:53 -0700)
committerSara Golemon <sgolemon@fb.com>
Thu, 11 Jun 2015 21:50:32 +0000 (14:50 -0700)
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

folly/experimental/fibers/Fiber.cpp
folly/experimental/fibers/FiberManager-inl.h
folly/futures/QueuedImmediateExecutor.cpp
folly/futures/QueuedImmediateExecutor.h

index 2a562774728d5d388425e359fa2d54847153c6cf..e66752acee3baa6d6853e4dc496c44a663a964e8 100644 (file)
@@ -34,7 +34,12 @@ namespace {
 static const uint64_t kMagic8Bytes = 0xfaceb00cfaceb00c;
 
 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;
 }
 
index c0f0d557def4aeeedec747a9285a3a2cfaeb4012..42d14ac0360ba547e17eda3350cf521bd7e3129b 100644 (file)
 #include <cassert>
 
 #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/Fiber.h>
 #include <folly/experimental/fibers/LoopController.h>
 #include <folly/experimental/fibers/Promise.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 {
 
@@ -454,8 +455,8 @@ T& FiberManager::local() {
 
 template <typename T>
 T& FiberManager::localThread() {
-  static thread_local T t;
-  return t;
+  static ThreadLocal<T> t;
+  return *t;
 }
 
 inline void FiberManager::initLocalData(Fiber& fiber) {
index 659f3f135352d4e99d79be26580957fd6d10bc5c..47b298f5dcb420d57b0cc4f7ed547874a30b76c1 100644 (file)
 
 namespace folly {
 
-void QueuedImmediateExecutor::add(Func callback) {
-  thread_local std::queue<Func> q;
+void QueuedImmediateExecutor::addStatic(Func callback) {
+  static folly::ThreadLocal<std::queue<Func>> q_;
 
-  if (q.empty()) {
-    q.push(std::move(callback));
-    while (!q.empty()) {
-      q.front()();
-      q.pop();
+  if (q_->empty()) {
+    q_->push(std::move(callback));
+    while (!q_->empty()) {
+      q_->front()();
+      q_->pop();
     }
   } else {
-    q.push(callback);
+    q_->push(callback);
   }
 }
 
index 15e2513f98d8fb2e7b8a99624fd52e5ba4e458bc..d1faa7e7d0051134bad6983b53a08b8eb224bcba 100644 (file)
@@ -27,7 +27,13 @@ namespace folly {
  */
 class QueuedImmediateExecutor : public Executor {
  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