inline EventBaseLoopController::~EventBaseLoopController() {
callback_.cancelLoopCallback();
+ eventBaseKeepAlive_.reset();
}
inline void EventBaseLoopController::attachEventBase(
}
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();
}
}
bool awaitingScheduling_{false};
folly::EventBase* eventBase_{nullptr};
+ folly::EventBase::LoopKeepAlive eventBaseKeepAlive_;
ControllerCallback callback_;
DestructionCallback destructionCallback_;
FiberManager* fm_{nullptr};
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;
}
}
-inline bool FiberManager::loopUntilNoReady() {
+inline void FiberManager::loopUntilNoReady() {
+ return loopController_->runLoop();
+}
+
+inline void FiberManager::loopUntilNoReadyImpl() {
#ifndef _WIN32
if (UNLIKELY(!alternateSignalStackRegistered_)) {
registerAlternateSignalStack();
}
}
readyFibers_.splice(readyFibers_.end(), yieldedFibers_);
-
- return fibersActive_ > 0;
}
// We need this to be in a struct, not inlined in addTask, because clang crashes
/**
* 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.
DCHECK(fm.get() != nullptr);
ThreadLocalCache::erase(evb_);
- while (fm->hasTasks()) {
- fm->loopUntilNoReady();
- evb_.loopOnce();
- }
-
delete this;
}
*/
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.
if (scheduled_) {
scheduled_ = false;
- waiting = fm_->loopUntilNoReady();
+ runLoop();
+ waiting = fm_->hasTasks();
}
}
}
return remoteScheduleCalled_;
}
+ void runLoop() override {
+ fm_->loopUntilNoReadyImpl();
+ }
+
void schedule() override {
scheduled_ = true;
}