Use loopKeepAlive() mechanism in FiberManager
authorAndrii Grynenko <andrii@fb.com>
Thu, 3 Nov 2016 00:39:29 +0000 (17:39 -0700)
committerFacebook Github Bot <facebook-github-bot-bot@fb.com>
Thu, 3 Nov 2016 00:53:32 +0000 (17:53 -0700)
Reviewed By: yfeldblum

Differential Revision: D4086486

fbshipit-source-id: bd0cca8dd2c9b74d5c30e4cd095191c1d1ecab79

folly/fibers/EventBaseLoopController-inl.h
folly/fibers/EventBaseLoopController.h
folly/fibers/FiberManagerInternal-inl.h
folly/fibers/FiberManagerInternal.h
folly/fibers/FiberManagerMap.cpp
folly/fibers/LoopController.h
folly/fibers/SimpleLoopController.h

index 0e4c2fd7d5c8e8b131a68dd37a2163e99c0316ce..89a0ece34474f7646df8c6445d8a7ec644fb9a63 100644 (file)
@@ -24,6 +24,7 @@ inline EventBaseLoopController::EventBaseLoopController()
 
 inline EventBaseLoopController::~EventBaseLoopController() {
   callback_.cancelLoopCallback();
+  eventBaseKeepAlive_.reset();
 }
 
 inline void EventBaseLoopController::attachEventBase(
@@ -62,10 +63,16 @@ inline void EventBaseLoopController::cancel() {
 }
 
 inline void EventBaseLoopController::runLoop() {
+  if (!eventBaseKeepAlive_) {
+    eventBaseKeepAlive_ = eventBase_->loopKeepAlive();
+  }
   if (loopRunner_) {
-    loopRunner_->run([&] { fm_->loopUntilNoReady(); });
+    loopRunner_->run([&] { fm_->loopUntilNoReadyImpl(); });
   } else {
-    fm_->loopUntilNoReady();
+    fm_->loopUntilNoReadyImpl();
+  }
+  if (!fm_->hasTasks()) {
+    eventBaseKeepAlive_.reset();
   }
 }
 
index 017b75228af66511c36d52e5ff40fc606b118c92..80dd6667677cb73ecbcc56ac19a4894e113722a4 100644 (file)
@@ -91,6 +91,7 @@ class EventBaseLoopController : public LoopController {
 
   bool awaitingScheduling_{false};
   folly::EventBase* eventBase_{nullptr};
+  folly::EventBase::LoopKeepAlive eventBaseKeepAlive_;
   ControllerCallback callback_;
   DestructionCallback destructionCallback_;
   FiberManager* fm_{nullptr};
@@ -103,7 +104,7 @@ class EventBaseLoopController : public LoopController {
   void setFiberManager(FiberManager* fm) override;
   void schedule() override;
   void cancel() override;
-  void runLoop();
+  void runLoop() override;
   void scheduleThreadSafe(std::function<bool()> func) override;
   void timedSchedule(std::function<void()> func, TimePoint time) override;
 
index 4c8878ba202a011e36f66d94c72cb6dc63945e47..fa526288e5ea3b72845db73c5f76e0f5988d2394 100644 (file)
@@ -185,7 +185,11 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
   }
 }
 
-inline bool FiberManager::loopUntilNoReady() {
+inline void FiberManager::loopUntilNoReady() {
+  return loopController_->runLoop();
+}
+
+inline void FiberManager::loopUntilNoReadyImpl() {
 #ifndef _WIN32
   if (UNLIKELY(!alternateSignalStackRegistered_)) {
     registerAlternateSignalStack();
@@ -243,8 +247,6 @@ inline bool FiberManager::loopUntilNoReady() {
     }
   }
   readyFibers_.splice(readyFibers_.end(), yieldedFibers_);
-
-  return fibersActive_ > 0;
 }
 
 // We need this to be in a struct, not inlined in addTask, because clang crashes
index dc0c3e6c8352573b4de3a8b177a630b0ae0ff7e9..28c74db641d97178f58fab32cda8b6456a7414a3 100644 (file)
@@ -155,10 +155,13 @@ class FiberManager : public ::folly::Executor {
 
   /**
    * Keeps running ready tasks until the list of ready tasks is empty.
-   *
-   * @return True if there are any waiting tasks remaining.
    */
-  bool loopUntilNoReady();
+  void loopUntilNoReady();
+
+  /**
+   * This should only be called by a LoopController.
+   */
+  void loopUntilNoReadyImpl();
 
   /**
    * @return true if there are outstanding tasks.
index 4548137100e0e263a4f66bb6efe0e88748292228..4a45e665a6e520b49c9c5fa72bb6c76ba6b751c8 100644 (file)
@@ -170,11 +170,6 @@ void EventBaseOnDestructionCallback::runLoopCallback() noexcept {
   DCHECK(fm.get() != nullptr);
   ThreadLocalCache::erase(evb_);
 
-  while (fm->hasTasks()) {
-    fm->loopUntilNoReady();
-    evb_.loopOnce();
-  }
-
   delete this;
 }
 
index 917a65575a62ea17248b7627e1ad830baeb563a0..19cace4e397b353583968a2b69b72258e657eb70 100644 (file)
@@ -41,6 +41,12 @@ class LoopController {
    */
   virtual void schedule() = 0;
 
+  /**
+   * Run FiberManager loopUntilNoReadyImpl(). May have additional logic specific
+   * to a LoopController.
+   */
+  virtual void runLoop() = 0;
+
   /**
    * Same as schedule(), but safe to call from any thread.
    * Runs func and only schedules if func returned true.
index 8c728bd6e5dd0c70bbbd6e09b2c22e11455f0f9c..7928424e0f01b1f93c5049d68fb99182cce685ad 100644 (file)
@@ -54,7 +54,8 @@ class SimpleLoopController : public LoopController {
 
       if (scheduled_) {
         scheduled_ = false;
-        waiting = fm_->loopUntilNoReady();
+        runLoop();
+        waiting = fm_->hasTasks();
       }
     }
   }
@@ -70,6 +71,10 @@ class SimpleLoopController : public LoopController {
     return remoteScheduleCalled_;
   }
 
+  void runLoop() override {
+    fm_->loopUntilNoReadyImpl();
+  }
+
   void schedule() override {
     scheduled_ = true;
   }