Make EventBaseLoopController only support VirtualEventBase v2017.03.13.00
authorAndrii Grynenko <andrii@fb.com>
Sat, 11 Mar 2017 01:06:58 +0000 (17:06 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Sat, 11 Mar 2017 01:19:39 +0000 (17:19 -0800)
Summary: EventBase support is achieved through default VirtualEventBase mechanism.

Reviewed By: yfeldblum

Differential Revision: D4685948

fbshipit-source-id: 15c8c789a55776984aa9087455e3f7b79d7604ad

folly/fibers/EventBaseLoopController-inl.h
folly/fibers/EventBaseLoopController.h
folly/fibers/FiberManagerMap.cpp
folly/io/async/EventBase.cpp
folly/io/async/VirtualEventBase.h

index 4c01ed006104b648660f6826c9cbfd7a384a0492..f0aa4c9b26a1ce8b17945a31bb70508e69a4bcd4 100644 (file)
 namespace folly {
 namespace fibers {
 
 namespace folly {
 namespace fibers {
 
-template <typename EventBaseT>
-inline EventBaseLoopControllerT<EventBaseT>::EventBaseLoopControllerT()
+inline EventBaseLoopController::EventBaseLoopController()
     : callback_(*this), aliveWeak_(destructionCallback_.getWeak()) {}
 
     : callback_(*this), aliveWeak_(destructionCallback_.getWeak()) {}
 
-template <typename EventBaseT>
-inline EventBaseLoopControllerT<EventBaseT>::~EventBaseLoopControllerT() {
+inline EventBaseLoopController::~EventBaseLoopController() {
   callback_.cancelLoopCallback();
   eventBaseKeepAlive_.reset();
 }
 
   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";
   }
   if (eventBase_ != nullptr) {
     LOG(ERROR) << "Attempt to reattach EventBase to LoopController";
   }
@@ -46,26 +47,11 @@ inline void EventBaseLoopControllerT<EventBaseT>::attachEventBase(
   }
 }
 
   }
 }
 
-template <typename EventBaseT>
-inline void EventBaseLoopControllerT<EventBaseT>::setFiberManager(
-    FiberManager* fm) {
+inline void EventBaseLoopController::setFiberManager(FiberManager* fm) {
   fm_ = 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;
   if (eventBase_ == nullptr) {
     // In this case we need to postpone scheduling.
     awaitingScheduling_ = true;
@@ -80,13 +66,11 @@ inline void EventBaseLoopControllerT<folly::VirtualEventBase>::schedule() {
   }
 }
 
   }
 }
 
-template <typename EventBaseT>
-inline void EventBaseLoopControllerT<EventBaseT>::cancel() {
+inline void EventBaseLoopController::cancel() {
   callback_.cancelLoopCallback();
 }
 
   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.
   if (!eventBaseKeepAlive_) {
     // runLoop can be called twice if both schedule() and scheduleThreadSafe()
     // were called.
@@ -105,8 +89,7 @@ inline void EventBaseLoopControllerT<EventBaseT>::runLoop() {
   }
 }
 
   }
 }
 
-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
     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
@@ -127,8 +110,7 @@ inline void EventBaseLoopControllerT<EventBaseT>::scheduleThreadSafe(
   }
 }
 
   }
 }
 
-template <typename EventBaseT>
-inline void EventBaseLoopControllerT<EventBaseT>::timedSchedule(
+inline void EventBaseLoopController::timedSchedule(
     std::function<void()> func,
     TimePoint time) {
   assert(eventBaseAttached_);
     std::function<void()> func,
     TimePoint time) {
   assert(eventBaseAttached_);
index ce97240b3bd83549b309a9e831dda950837d1dbb..a8a827668a1ba65e0dcfb224fa031504e2b46b46 100644 (file)
 
 #include <folly/fibers/FiberManagerInternal.h>
 #include <folly/fibers/LoopController.h>
 
 #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>
 
 #include <folly/io/async/VirtualEventBase.h>
 #include <atomic>
 #include <memory>
 
-namespace folly {
-class EventBase;
-}
-
 namespace folly {
 namespace fibers {
 
 namespace folly {
 namespace fibers {
 
-template <typename EventBaseT>
-class EventBaseLoopControllerT : public LoopController {
+class EventBaseLoopController : public LoopController {
  public:
  public:
-  explicit EventBaseLoopControllerT();
-  ~EventBaseLoopControllerT();
+  explicit EventBaseLoopController();
+  ~EventBaseLoopController();
 
   /**
    * Attach EventBase after LoopController was created.
    */
 
   /**
    * Attach EventBase after LoopController was created.
    */
-  void attachEventBase(EventBaseT& eventBase);
+  void attachEventBase(EventBase& eventBase);
+  void attachEventBase(VirtualEventBase& eventBase);
 
 
-  EventBaseT* getEventBase() {
+  VirtualEventBase* getEventBase() {
     return eventBase_;
   }
 
     return eventBase_;
   }
 
@@ -51,7 +46,7 @@ class EventBaseLoopControllerT : public LoopController {
  private:
   class ControllerCallback : public folly::EventBase::LoopCallback {
    public:
  private:
   class ControllerCallback : public folly::EventBase::LoopCallback {
    public:
-    explicit ControllerCallback(EventBaseLoopControllerT& controller)
+    explicit ControllerCallback(EventBaseLoopController& controller)
         : controller_(controller) {}
 
     void runLoopCallback() noexcept override {
         : controller_(controller) {}
 
     void runLoopCallback() noexcept override {
@@ -59,7 +54,7 @@ class EventBaseLoopControllerT : public LoopController {
     }
 
    private:
     }
 
    private:
-    EventBaseLoopControllerT& controller_;
+    EventBaseLoopController& controller_;
   };
 
   class DestructionCallback : public folly::EventBase::LoopCallback {
   };
 
   class DestructionCallback : public folly::EventBase::LoopCallback {
@@ -92,7 +87,7 @@ class EventBaseLoopControllerT : public LoopController {
   };
 
   bool awaitingScheduling_{false};
   };
 
   bool awaitingScheduling_{false};
-  EventBaseT* eventBase_{nullptr};
+  VirtualEventBase* eventBase_{nullptr};
   Executor::KeepAlive eventBaseKeepAlive_;
   ControllerCallback callback_;
   DestructionCallback destructionCallback_;
   Executor::KeepAlive eventBaseKeepAlive_;
   ControllerCallback callback_;
   DestructionCallback destructionCallback_;
@@ -113,9 +108,6 @@ class EventBaseLoopControllerT : public LoopController {
   friend class FiberManager;
 };
 
   friend class FiberManager;
 };
 
-using EventBaseLoopController = EventBaseLoopControllerT<folly::EventBase>;
-using VirtualEventBaseLoopController =
-    EventBaseLoopControllerT<folly::VirtualEventBase>;
 }
 } // folly::fibers
 
 }
 } // folly::fibers
 
index 8e294c12fab36c3dab76322e21cbe9fc47a2deec..5e2eebca55c8d73ae232e9ad2a2f785a50c7f631 100644 (file)
@@ -63,7 +63,7 @@ class GlobalCache {
     auto& fmPtrRef = map_[&evb];
 
     if (!fmPtrRef) {
     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));
 
       loopController->attachEventBase(evb);
       evb.runOnDestruction(new EventBaseOnDestructionCallback<EventBaseT>(evb));
 
index 062ec2d3dd4e1f2726a31644eb126cb6a7311115..1f5ea560f61a34737f1eedfaad3ff142dd717f0d 100644 (file)
@@ -408,16 +408,23 @@ ssize_t EventBase::loopKeepAliveCount() {
         loopKeepAliveCountAtomic_.exchange(0, std::memory_order_relaxed);
   }
   DCHECK_GE(loopKeepAliveCount_, 0);
         loopKeepAliveCountAtomic_.exchange(0, std::memory_order_relaxed);
   }
   DCHECK_GE(loopKeepAliveCount_, 0);
+
   return loopKeepAliveCount_;
 }
 
 void EventBase::applyLoopKeepAlive() {
   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;
     // 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.
     // 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.
index a1194d82ab3f994d0106b1e4262e5348bd2cce1a..4719fdeac09abbf0a936dd88732c306fd54050c0 100644 (file)
@@ -137,7 +137,7 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager {
 
  protected:
   void keepAliveRelease() override {
 
  protected:
   void keepAliveRelease() override {
-    DCHECK(getEventBase().inRunningEventBaseThread());
+    DCHECK(getEventBase().isInEventBaseThread());
     if (loopKeepAliveCountAtomic_.load()) {
       loopKeepAliveCount_ += loopKeepAliveCountAtomic_.exchange(0);
     }
     if (loopKeepAliveCountAtomic_.load()) {
       loopKeepAliveCount_ += loopKeepAliveCountAtomic_.exchange(0);
     }
@@ -150,6 +150,13 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager {
  private:
   friend class EventBase;
 
  private:
   friend class EventBase;
 
+  ssize_t keepAliveCount() {
+    if (loopKeepAliveCountAtomic_.load()) {
+      loopKeepAliveCount_ += loopKeepAliveCountAtomic_.exchange(0);
+    }
+    return loopKeepAliveCount_;
+  }
+
   std::future<void> destroy();
   void destroyImpl();
 
   std::future<void> destroy();
   void destroyImpl();