high init priority for FiberManagerMap data
authorMark McDuff <mcduff@fb.com>
Tue, 7 Jul 2015 22:20:59 +0000 (15:20 -0700)
committerSara Golemon <sgolemon@fb.com>
Thu, 9 Jul 2015 22:32:54 +0000 (15:32 -0700)
Summary: Ran into a bug in D2158570 where we dtor'ing these data structures before the event bases destructed, so the assert on line 47 (of the old code) failed.

Reviewed By: @andriigrynenko

Differential Revision: D2198318

folly/experimental/fibers/FiberManagerMap.cpp

index 355facbcad39627bf5922f4f7a1142b14a142aaa..9e63bd51d0d3e1d947c930ac753e5a12f0039e46 100644 (file)
 
 namespace folly { namespace fibers {
 
-namespace detail {
+namespace {
 
+// Leak these intentionally.  During shutdown, we may call getFiberManager, and
+// want access to the fiber managers during that time.
 class LocalFiberManagerMapTag;
-folly::ThreadLocal<std::unordered_map<folly::EventBase*, FiberManager*>,
-  LocalFiberManagerMapTag> localFiberManagerMap;
-std::unordered_map<folly::EventBase*, std::unique_ptr<FiberManager>>
-    fiberManagerMap;
-std::mutex fiberManagerMapMutex;
+typedef folly::ThreadLocal<
+    std::unordered_map<folly::EventBase*, FiberManager*>,
+    LocalFiberManagerMapTag>
+  LocalMapType;
+LocalMapType* localFiberManagerMap() {
+  static auto ret = new LocalMapType();
+  return ret;
+}
+
+typedef
+  std::unordered_map<folly::EventBase*, std::unique_ptr<FiberManager>>
+  MapType;
+MapType* fiberManagerMap() {
+  static auto ret = new MapType();
+  return ret;
+}
+
+std::mutex* fiberManagerMapMutex() {
+  static auto ret = new std::mutex();
+  return ret;
+}
+
 
 class OnEventBaseDestructionCallback : public folly::EventBase::LoopCallback {
  public:
   explicit OnEventBaseDestructionCallback(folly::EventBase& evb)
            : evb_(&evb) {}
   void runLoopCallback() noexcept override {
-    for (auto& localMap : localFiberManagerMap.accessAllThreads()) {
+    for (auto& localMap : localFiberManagerMap()->accessAllThreads()) {
       localMap.erase(evb_);
     }
     std::unique_ptr<FiberManager> fm;
     {
-      std::lock_guard<std::mutex> lg(fiberManagerMapMutex);
-      auto it = fiberManagerMap.find(evb_);
-      assert(it != fiberManagerMap.end());
+      std::lock_guard<std::mutex> lg(*fiberManagerMapMutex());
+      auto it = fiberManagerMap()->find(evb_);
+      assert(it != fiberManagerMap()->end());
       fm = std::move(it->second);
-      fiberManagerMap.erase(it);
+      fiberManagerMap()->erase(it);
     }
     assert(fm.get() != nullptr);
     fm->loopUntilNoReady();
@@ -58,10 +77,10 @@ class OnEventBaseDestructionCallback : public folly::EventBase::LoopCallback {
 
 FiberManager* getFiberManagerThreadSafe(folly::EventBase& evb,
                                         const FiberManager::Options& opts) {
-  std::lock_guard<std::mutex> lg(fiberManagerMapMutex);
+  std::lock_guard<std::mutex> lg(*fiberManagerMapMutex());
 
-  auto it = fiberManagerMap.find(&evb);
-  if (LIKELY(it != fiberManagerMap.end())) {
+  auto it = fiberManagerMap()->find(&evb);
+  if (LIKELY(it != fiberManagerMap()->end())) {
     return it->second.get();
   }
 
@@ -69,22 +88,22 @@ FiberManager* getFiberManagerThreadSafe(folly::EventBase& evb,
   loopController->attachEventBase(evb);
   auto fiberManager =
       folly::make_unique<FiberManager>(std::move(loopController), opts);
-  auto result = fiberManagerMap.emplace(&evb, std::move(fiberManager));
+  auto result = fiberManagerMap()->emplace(&evb, std::move(fiberManager));
   evb.runOnDestruction(new OnEventBaseDestructionCallback(evb));
   return result.first->second.get();
 }
 
-} // detail namespace
+} // namespace
 
 FiberManager& getFiberManager(folly::EventBase& evb,
                               const FiberManager::Options& opts) {
-  auto it = detail::localFiberManagerMap->find(&evb);
-  if (LIKELY(it != detail::localFiberManagerMap->end())) {
+  auto it = (*localFiberManagerMap())->find(&evb);
+  if (LIKELY(it != (*localFiberManagerMap())->end())) {
     return *(it->second);
   }
 
-  auto fm = detail::getFiberManagerThreadSafe(evb, opts);
-  detail::localFiberManagerMap->emplace(&evb, fm);
+  auto fm = getFiberManagerThreadSafe(evb, opts);
+  (*localFiberManagerMap())->emplace(&evb, fm);
   return *fm;
 }