logging: add a FileHandlerFactory class
[folly.git] / folly / detail / ThreadLocalDetail.h
index fe72161a2a618d8a4e76a1db2142feecc440ab82..735541b5cec999572b10b80729b2e4d80ea1dd27 100644 (file)
 #include <glog/logging.h>
 
 #include <folly/Exception.h>
-#include <folly/Foreach.h>
 #include <folly/Function.h>
-#include <folly/Malloc.h>
 #include <folly/MicroSpinLock.h>
 #include <folly/Portability.h>
 #include <folly/ScopeGuard.h>
 #include <folly/SharedMutex.h>
+#include <folly/container/Foreach.h>
+#include <folly/memory/Malloc.h>
 #include <folly/portability/PThread.h>
 
 #include <folly/detail/StaticSingletonManager.h>
@@ -290,7 +290,7 @@ struct StaticMetaBase {
    */
   void reserve(EntryID* id);
 
-  ElementWrapper& get(EntryID* ent);
+  ElementWrapper& getElement(EntryID* ent);
 
   static void initAtFork();
   static void registerAtFork(
@@ -335,7 +335,35 @@ struct StaticMeta : StaticMetaBase {
     return *instance;
   }
 
-  ElementWrapper& get(EntryID* ent) {
+#ifdef FOLLY_TLD_USE_FOLLY_TLS
+  // Eliminate as many branches as possible:
+  // One branch on capacityCache, vs. three:
+  // 1) instance() static initializer
+  // 2) getThreadEntry null check
+  // 3) elementsCapacity size check.
+  // 3 will never be true if 1 or 2 are false.
+  FOLLY_ALWAYS_INLINE static ElementWrapper& get(EntryID* ent) {
+    uint32_t id = ent->getOrInvalid();
+    if (UNLIKELY(capacityCache_ <= id)) {
+      return getSlow(ent);
+    } else {
+      return threadEntryCache_->elements[id];
+    }
+  }
+
+  static ElementWrapper& getSlow(EntryID* ent) {
+    ElementWrapper& res = instance().getElement(ent);
+    // Cache new capacity
+    capacityCache_ = getThreadEntry()->elementsCapacity;
+    return res;
+  }
+#else
+  static ElementWrapper& get(EntryID* ent) {
+    return instance().getElement(ent);
+  }
+#endif
+
+  ElementWrapper& getElement(EntryID* ent) {
     ThreadEntry* threadEntry = getThreadEntry();
     uint32_t id = ent->getOrInvalid();
     // if id is invalid, it is equal to uint32_t's max value.
@@ -369,23 +397,24 @@ struct StaticMeta : StaticMetaBase {
 
   inline static ThreadEntry* getThreadEntry() {
 #ifdef FOLLY_TLD_USE_FOLLY_TLS
-    static FOLLY_TLS ThreadEntry* threadEntryCache{nullptr};
-    if (UNLIKELY(threadEntryCache == nullptr)) {
-      threadEntryCache = instance().threadEntry_();
+    if (UNLIKELY(threadEntryCache_ == nullptr)) {
+      threadEntryCache_ = instance().threadEntry_();
     }
-    return threadEntryCache;
+    return threadEntryCache_;
 #else
     return instance().threadEntry_();
 #endif
   }
 
-  static void preFork(void) {
+  static void preFork() {
     instance().lock_.lock();  // Make sure it's created
   }
 
-  static void onForkParent(void) { instance().lock_.unlock(); }
+  static void onForkParent() {
+    instance().lock_.unlock();
+  }
 
-  static void onForkChild(void) {
+  static void onForkChild() {
     // only the current thread survives
     instance().head_.next = instance().head_.prev = &instance().head_;
     ThreadEntry* threadEntry = getThreadEntry();
@@ -395,7 +424,18 @@ struct StaticMeta : StaticMetaBase {
     }
     instance().lock_.unlock();
   }
+
+#ifdef FOLLY_TLD_USE_FOLLY_TLS
+  static FOLLY_TLS ThreadEntry* threadEntryCache_;
+  static FOLLY_TLS size_t capacityCache_;
+#endif
 };
 
-}  // namespace threadlocal_detail
-}  // namespace folly
+#ifdef FOLLY_TLD_USE_FOLLY_TLS
+template <class Tag, class AccessMode>
+FOLLY_TLS ThreadEntry* StaticMeta<Tag, AccessMode>::threadEntryCache_{nullptr};
+template <class Tag, class AccessMode>
+FOLLY_TLS size_t StaticMeta<Tag, AccessMode>::capacityCache_{0};
+#endif
+} // namespace threadlocal_detail
+} // namespace folly