From bf52653d56e76857cf2712f36c034ae9f8bb15c6 Mon Sep 17 00:00:00 2001 From: Mark McDuff Date: Tue, 7 Jul 2015 15:20:59 -0700 Subject: [PATCH] high init priority for FiberManagerMap data 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 | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/folly/experimental/fibers/FiberManagerMap.cpp b/folly/experimental/fibers/FiberManagerMap.cpp index 355facbc..9e63bd51 100644 --- a/folly/experimental/fibers/FiberManagerMap.cpp +++ b/folly/experimental/fibers/FiberManagerMap.cpp @@ -23,30 +23,49 @@ 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, - LocalFiberManagerMapTag> localFiberManagerMap; -std::unordered_map> - fiberManagerMap; -std::mutex fiberManagerMapMutex; +typedef folly::ThreadLocal< + std::unordered_map, + LocalFiberManagerMapTag> + LocalMapType; +LocalMapType* localFiberManagerMap() { + static auto ret = new LocalMapType(); + return ret; +} + +typedef + std::unordered_map> + 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 fm; { - std::lock_guard lg(fiberManagerMapMutex); - auto it = fiberManagerMap.find(evb_); - assert(it != fiberManagerMap.end()); + std::lock_guard 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 lg(fiberManagerMapMutex); + std::lock_guard 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(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; } -- 2.34.1