Fix copyright line in folly/synchronization/test/ParkingLotBenchmark.cpp
[folly.git] / folly / experimental / TLRefCount.h
index 78054edd0a1719505bfe0c0169a9d1637b4c90b5..47f9c599a6a62ff2d00a127d27f9fa3fd4391866 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2015-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
 #pragma once
 
 #include <folly/ThreadLocal.h>
-#include <folly/experimental/AsymmetricMemoryBarrier.h>
+#include <folly/synchronization/AsymmetricMemoryBarrier.h>
 
 namespace folly {
 
@@ -81,25 +81,47 @@ class TLRefCount {
   }
 
   void useGlobal() noexcept {
-    std::lock_guard<std::mutex> lg(globalMutex_);
+    std::array<TLRefCount*, 1> ptrs{{this}};
+    useGlobal(ptrs);
+  }
 
-    state_ = State::GLOBAL_TRANSITION;
+  template <typename Container>
+  static void useGlobal(const Container& refCountPtrs) {
+#ifdef FOLLY_SANITIZE_THREAD
+    // TSAN has a limitation for the number of locks held concurrently, so it's
+    // safer to call useGlobal() serially.
+    if (refCountPtrs.size() > 1) {
+      for (auto refCountPtr : refCountPtrs) {
+        refCountPtr->useGlobal();
+      }
+      return;
+    }
+#endif
+
+    std::vector<std::unique_lock<std::mutex>> lgs_;
+    for (auto refCountPtr : refCountPtrs) {
+      lgs_.emplace_back(refCountPtr->globalMutex_);
+
+      refCountPtr->state_ = State::GLOBAL_TRANSITION;
+    }
 
     asymmetricHeavyBarrier();
 
-    std::weak_ptr<void> collectGuardWeak = collectGuard_;
+    for (auto refCountPtr : refCountPtrs) {
+      std::weak_ptr<void> collectGuardWeak = refCountPtr->collectGuard_;
 
-    // Make sure we can't create new LocalRefCounts
-    collectGuard_.reset();
+      // Make sure we can't create new LocalRefCounts
+      refCountPtr->collectGuard_.reset();
 
-    while (!collectGuardWeak.expired()) {
-      auto accessor = localCount_.accessAllThreads();
-      for (auto& count : accessor) {
-        count.collect();
+      while (!collectGuardWeak.expired()) {
+        auto accessor = refCountPtr->localCount_.accessAllThreads();
+        for (auto& count : accessor) {
+          count.collect();
+        }
       }
-    }
 
-    state_ = State::GLOBAL;
+      refCountPtr->state_ = State::GLOBAL;
+    }
   }
 
  private:
@@ -188,4 +210,4 @@ class TLRefCount {
   std::shared_ptr<void> collectGuard_;
 };
 
-}
+} // namespace folly