From: Andrii Grynenko Date: Mon, 6 Apr 2015 19:06:58 +0000 (-0700) Subject: Add FiberManager local type X-Git-Tag: v0.35.0~13 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=0978159b6279d9484a6612c5e46193376fd83820;p=folly.git Add FiberManager local type Summary: This adds local type for each FiberManager. Only local of given type can be created on fibers of this FiberManager. Locals of other types will be just treated as regualar thread-locals. Test Plan: unit test Reviewed By: bwatling@fb.com Subscribers: folly-diffs@, yfeldblum, chalfant FB internal diff: D1969739 Signature: t1:1969739:1428345931:aff5deb526c179158e5881b29330ff3f6698149a --- diff --git a/folly/AtomicLinkedList.h b/folly/AtomicLinkedList.h index 7e9db6bd..eca8de16 100644 --- a/folly/AtomicLinkedList.h +++ b/folly/AtomicLinkedList.h @@ -44,6 +44,20 @@ template T::* HookMember> class AtomicLinkedList { public: AtomicLinkedList() {} + AtomicLinkedList(const AtomicLinkedList&) = delete; + AtomicLinkedList& operator=(const AtomicLinkedList&) = delete; + AtomicLinkedList(AtomicLinkedList&& other) noexcept { + auto tmp = other.head_.load(); + other.head_ = head_.load(); + head_ = tmp; + } + AtomicLinkedList& operator=(AtomicLinkedList&& other) noexcept { + auto tmp = other.head_.load(); + other.head_ = head_.load(); + head_ = tmp; + + return *this; + } /** * Note: list must be empty on destruction. diff --git a/folly/experimental/fibers/FiberManager-inl.h b/folly/experimental/fibers/FiberManager-inl.h index 16c5b988..f56b0640 100644 --- a/folly/experimental/fibers/FiberManager-inl.h +++ b/folly/experimental/fibers/FiberManager-inl.h @@ -174,9 +174,7 @@ void FiberManager::addTask(F&& func) { typedef AddTaskHelper Helper; auto fiber = getFiber(); - if (currentFiber_) { - fiber->localData_ = currentFiber_->localData_; - } + initLocalData(*fiber); if (Helper::allocateInBuffer) { auto funcLoc = static_cast(fiber->getUserBuffer()); @@ -199,7 +197,9 @@ template void FiberManager::addTaskRemote(F&& func) { auto task = [&]() { auto currentFm = getFiberManagerUnsafe(); - if (currentFm && currentFm->currentFiber_) { + if (currentFm && + currentFm->currentFiber_ && + currentFm->localType_ == localType_) { return folly::make_unique( std::forward(func), currentFm->currentFiber_->localData_); @@ -297,9 +297,7 @@ void FiberManager::addTaskFinally(F&& func, G&& finally) { "finally(Try&&): T must be convertible from func()'s return type"); auto fiber = getFiber(); - if (currentFiber_) { - fiber->localData_ = currentFiber_->localData_; - } + initLocalData(*fiber); typedef AddTaskFinallyHelper Helper; @@ -383,7 +381,7 @@ inline bool FiberManager::hasActiveFiber() const { template T& FiberManager::local() { - if (currentFiber_) { + if (std::type_index(typeid(T)) == localType_ && currentFiber_) { return currentFiber_->localData_.get(); } return localThread(); @@ -395,6 +393,22 @@ T& FiberManager::localThread() { return t; } +inline void FiberManager::initLocalData(Fiber& fiber) { + auto fm = getFiberManagerUnsafe(); + if (fm && fm->currentFiber_ && fm->localType_ == localType_) { + fiber.localData_ = fm->currentFiber_->localData_; + } +} + +template +FiberManager FiberManager::create( + std::unique_ptr loopController, + Options options) { + FiberManager fm(std::move(loopController), std::move(options)); + fm.localType_ = typeid(LocalT); + return fm; +} + template typename FirstArgOf::type::value_type inline await(F&& func) { diff --git a/folly/experimental/fibers/FiberManager.cpp b/folly/experimental/fibers/FiberManager.cpp index 2d88601a..5fb6bb95 100644 --- a/folly/experimental/fibers/FiberManager.cpp +++ b/folly/experimental/fibers/FiberManager.cpp @@ -48,7 +48,8 @@ FiberManager::FiberManager(std::unique_ptr loopController, throw; } }), - timeoutManager_(std::make_shared(*loopController_)) { + timeoutManager_(std::make_shared(*loopController_)), + localType_(typeid(void)) { loopController_->setFiberManager(this); } diff --git a/folly/experimental/fibers/FiberManager.h b/folly/experimental/fibers/FiberManager.h index d1f3ce1d..94e6c289 100644 --- a/folly/experimental/fibers/FiberManager.h +++ b/folly/experimental/fibers/FiberManager.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -91,14 +92,33 @@ class FiberManager { typedef std::function ExceptionCallback; + FiberManager(const FiberManager&) = delete; + FiberManager& operator=(const FiberManager&) = delete; + FiberManager(FiberManager&&) = default; + FiberManager& operator=(FiberManager&&) = default; + /** * Initializes, but doesn't start FiberManager loop * + * @param loopController * @param options FiberManager options */ explicit FiberManager(std::unique_ptr loopController, Options options = Options()); + /** + * Initializes, but doesn't start FiberManager loop + * + * @param loopController + * @param options FiberManager options + * @tparam LocalT only local of this type may be stored on fibers. + * Locals of other types will be considered thread-locals. + */ + template + static FiberManager create(std::unique_ptr loopController, + Options options = Options()); + + ~FiberManager(); /** @@ -300,6 +320,11 @@ class FiberManager { */ Fiber* getFiber(); + /** + * Sets local data for given fiber if all conditions are met. + */ + void initLocalData(Fiber& fiber); + /** * Function passed to the await call. */ @@ -319,6 +344,11 @@ class FiberManager { std::shared_ptr timeoutManager_; + /** + * Only local of this type will be available for fibers. + */ + std::type_index localType_; + void runReadyFiber(Fiber* fiber); void remoteReadyInsert(Fiber* fiber); }; diff --git a/folly/experimental/fibers/test/FibersTest.cpp b/folly/experimental/fibers/test/FibersTest.cpp index 0b79cafa..2aea08ab 100644 --- a/folly/experimental/fibers/test/FibersTest.cpp +++ b/folly/experimental/fibers/test/FibersTest.cpp @@ -1217,7 +1217,8 @@ TEST(FiberManager, remoteHasReadyTasks) { template void testFiberLocal() { - FiberManager fm(folly::make_unique()); + auto fm = + FiberManager::create(folly::make_unique()); fm.addTask([]() { EXPECT_EQ(42, local().value);