namespace folly {
namespace fibers {
-template <typename EventBaseT>
-inline EventBaseLoopControllerT<EventBaseT>::EventBaseLoopControllerT()
+inline EventBaseLoopController::EventBaseLoopController()
: callback_(*this), aliveWeak_(destructionCallback_.getWeak()) {}
-template <typename EventBaseT>
-inline EventBaseLoopControllerT<EventBaseT>::~EventBaseLoopControllerT() {
+inline EventBaseLoopController::~EventBaseLoopController() {
callback_.cancelLoopCallback();
eventBaseKeepAlive_.reset();
}
-template <typename EventBaseT>
-inline void EventBaseLoopControllerT<EventBaseT>::attachEventBase(
- EventBaseT& eventBase) {
+inline void EventBaseLoopController::attachEventBase(EventBase& eventBase) {
+ attachEventBase(eventBase.getVirtualEventBase());
+}
+
+inline void EventBaseLoopController::attachEventBase(
+ VirtualEventBase& eventBase) {
if (eventBase_ != nullptr) {
LOG(ERROR) << "Attempt to reattach EventBase to LoopController";
}
}
}
-template <typename EventBaseT>
-inline void EventBaseLoopControllerT<EventBaseT>::setFiberManager(
- FiberManager* fm) {
+inline void EventBaseLoopController::setFiberManager(FiberManager* fm) {
fm_ = fm;
}
-template <>
-inline void EventBaseLoopControllerT<folly::EventBase>::schedule() {
- if (eventBase_ == nullptr) {
- // In this case we need to postpone scheduling.
- awaitingScheduling_ = true;
- } else {
- // Schedule it to run in current iteration.
- eventBase_->runInLoop(&callback_, true);
- awaitingScheduling_ = false;
- }
-}
-
-template <>
-inline void EventBaseLoopControllerT<folly::VirtualEventBase>::schedule() {
+inline void EventBaseLoopController::schedule() {
if (eventBase_ == nullptr) {
// In this case we need to postpone scheduling.
awaitingScheduling_ = true;
}
}
-template <typename EventBaseT>
-inline void EventBaseLoopControllerT<EventBaseT>::cancel() {
+inline void EventBaseLoopController::cancel() {
callback_.cancelLoopCallback();
}
-template <typename EventBaseT>
-inline void EventBaseLoopControllerT<EventBaseT>::runLoop() {
+inline void EventBaseLoopController::runLoop() {
if (!eventBaseKeepAlive_) {
// runLoop can be called twice if both schedule() and scheduleThreadSafe()
// were called.
}
}
-template <typename EventBaseT>
-inline void EventBaseLoopControllerT<EventBaseT>::scheduleThreadSafe(
+inline void EventBaseLoopController::scheduleThreadSafe(
std::function<bool()> func) {
/* The only way we could end up here is if
1) Fiber thread creates a fiber that awaits (which means we must
}
}
-template <typename EventBaseT>
-inline void EventBaseLoopControllerT<EventBaseT>::timedSchedule(
+inline void EventBaseLoopController::timedSchedule(
std::function<void()> func,
TimePoint time) {
assert(eventBaseAttached_);
#include <folly/fibers/FiberManagerInternal.h>
#include <folly/fibers/LoopController.h>
-#include <folly/io/async/EventBase.h>
#include <folly/io/async/VirtualEventBase.h>
#include <atomic>
#include <memory>
-namespace folly {
-class EventBase;
-}
-
namespace folly {
namespace fibers {
-template <typename EventBaseT>
-class EventBaseLoopControllerT : public LoopController {
+class EventBaseLoopController : public LoopController {
public:
- explicit EventBaseLoopControllerT();
- ~EventBaseLoopControllerT();
+ explicit EventBaseLoopController();
+ ~EventBaseLoopController();
/**
* Attach EventBase after LoopController was created.
*/
- void attachEventBase(EventBaseT& eventBase);
+ void attachEventBase(EventBase& eventBase);
+ void attachEventBase(VirtualEventBase& eventBase);
- EventBaseT* getEventBase() {
+ VirtualEventBase* getEventBase() {
return eventBase_;
}
private:
class ControllerCallback : public folly::EventBase::LoopCallback {
public:
- explicit ControllerCallback(EventBaseLoopControllerT& controller)
+ explicit ControllerCallback(EventBaseLoopController& controller)
: controller_(controller) {}
void runLoopCallback() noexcept override {
}
private:
- EventBaseLoopControllerT& controller_;
+ EventBaseLoopController& controller_;
};
class DestructionCallback : public folly::EventBase::LoopCallback {
};
bool awaitingScheduling_{false};
- EventBaseT* eventBase_{nullptr};
+ VirtualEventBase* eventBase_{nullptr};
Executor::KeepAlive eventBaseKeepAlive_;
ControllerCallback callback_;
DestructionCallback destructionCallback_;
friend class FiberManager;
};
-using EventBaseLoopController = EventBaseLoopControllerT<folly::EventBase>;
-using VirtualEventBaseLoopController =
- EventBaseLoopControllerT<folly::VirtualEventBase>;
}
} // folly::fibers
auto& fmPtrRef = map_[&evb];
if (!fmPtrRef) {
- auto loopController = make_unique<EventBaseLoopControllerT<EventBaseT>>();
+ auto loopController = make_unique<EventBaseLoopController>();
loopController->attachEventBase(evb);
evb.runOnDestruction(new EventBaseOnDestructionCallback<EventBaseT>(evb));
loopKeepAliveCountAtomic_.exchange(0, std::memory_order_relaxed);
}
DCHECK_GE(loopKeepAliveCount_, 0);
+
return loopKeepAliveCount_;
}
void EventBase::applyLoopKeepAlive() {
- if (loopKeepAliveActive_ && loopKeepAliveCount() == 0) {
+ auto keepAliveCount = loopKeepAliveCount();
+ // Make sure default VirtualEventBase won't hold EventBase::loop() forever.
+ if (virtualEventBase_ && virtualEventBase_->keepAliveCount() == 1) {
+ --keepAliveCount;
+ }
+
+ if (loopKeepAliveActive_ && keepAliveCount == 0) {
// Restore the notification queue internal flag
fnRunner_->stopConsuming();
fnRunner_->startConsumingInternal(this, queue_.get());
loopKeepAliveActive_ = false;
- } else if (!loopKeepAliveActive_ && loopKeepAliveCount() > 0) {
+ } else if (!loopKeepAliveActive_ && keepAliveCount > 0) {
// Update the notification queue event to treat it as a normal
// (non-internal) event. The notification queue event always remains
// installed, and the main loop won't exit with it installed.
protected:
void keepAliveRelease() override {
- DCHECK(getEventBase().inRunningEventBaseThread());
+ DCHECK(getEventBase().isInEventBaseThread());
if (loopKeepAliveCountAtomic_.load()) {
loopKeepAliveCount_ += loopKeepAliveCountAtomic_.exchange(0);
}
private:
friend class EventBase;
+ ssize_t keepAliveCount() {
+ if (loopKeepAliveCountAtomic_.load()) {
+ loopKeepAliveCount_ += loopKeepAliveCountAtomic_.exchange(0);
+ }
+ return loopKeepAliveCount_;
+ }
+
std::future<void> destroy();
void destroyImpl();