logging: add a FileHandlerFactory class
[folly.git] / folly / detail / ThreadLocalDetail.h
index 3d5a2aa83c34433b0174399bbeccf3011771739d..735541b5cec999572b10b80729b2e4d80ea1dd27 100644 (file)
@@ -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,11 +397,10 @@ 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
@@ -397,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
 };
 
+#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