From: Andrii Grynenko Date: Sat, 20 Feb 2016 00:13:42 +0000 (-0800) Subject: Support nested FiberManagers X-Git-Tag: deprecate-dynamic-initializer~54 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=743a0b4850d9b4f6c72ee0427ffcfa30e2f53459;p=folly.git Support nested FiberManagers Summary:It's possible to have nested loopUntilNoReady (with different FiberManagers). See unit test for a simple example. This diff fixes currentFiberManager_ to be a stack. Reviewed By: meyering Differential Revision: D2953468 fb-gh-sync-id: 0abdcb7f43c94e7bb0adef8440699dc8e138d21a shipit-source-id: 0abdcb7f43c94e7bb0adef8440699dc8e138d21a --- diff --git a/folly/experimental/fibers/FiberManager-inl.h b/folly/experimental/fibers/FiberManager-inl.h index b0a6334e..61d4fec0 100644 --- a/folly/experimental/fibers/FiberManager-inl.h +++ b/folly/experimental/fibers/FiberManager-inl.h @@ -141,16 +141,19 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { } inline bool FiberManager::loopUntilNoReady() { + // Support nested FiberManagers + auto originalFiberManager = this; + std::swap(currentFiberManager_, originalFiberManager); + SCOPE_EXIT { isLoopScheduled_ = false; if (!readyFibers_.empty()) { ensureLoopScheduled(); } - currentFiberManager_ = nullptr; + std::swap(currentFiberManager_, originalFiberManager); + CHECK_EQ(this, originalFiberManager); }; - currentFiberManager_ = this; - bool hadRemoteFiber = true; while (hadRemoteFiber) { hadRemoteFiber = false; diff --git a/folly/experimental/fibers/test/FibersTest.cpp b/folly/experimental/fibers/test/FibersTest.cpp index b7c69c9c..f2c5ba97 100644 --- a/folly/experimental/fibers/test/FibersTest.cpp +++ b/folly/experimental/fibers/test/FibersTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1552,6 +1553,34 @@ TEST(FiberManager, remoteFutureTest) { EXPECT_EQ(v2, testValue2); } +TEST(FiberManager, nestedFiberManagers) { + folly::EventBase outerEvb; + folly::EventBase innerEvb; + + getFiberManager(outerEvb).addTask([&]() { + EXPECT_EQ(&getFiberManager(outerEvb), + FiberManager::getFiberManagerUnsafe()); + + runInMainContext([&]() { + getFiberManager(innerEvb).addTask([&]() { + EXPECT_EQ(&getFiberManager(innerEvb), + FiberManager::getFiberManagerUnsafe()); + + innerEvb.terminateLoopSoon(); + }); + + innerEvb.loopForever(); + }); + + EXPECT_EQ(&getFiberManager(outerEvb), + FiberManager::getFiberManagerUnsafe()); + + outerEvb.terminateLoopSoon(); + }); + + outerEvb.loopForever(); +} + static size_t sNumAwaits; void runBenchmark(size_t numAwaits, size_t toSend) {