apply clang-tidy modernize-use-override
[folly.git] / folly / io / async / VirtualEventBase.h
index c26f92cf6009f934d6a2587cf1c3b7d3630a78c8..d02fd0e59ea1e16f8bb0d1599c71290e38c29ee5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <future>
+
 #include <folly/Baton.h>
 #include <folly/Executor.h>
 #include <folly/io/async/EventBase.h>
@@ -27,7 +29,7 @@ namespace folly {
  *
  * Multiple VirtualEventBases can be backed by a single EventBase. Similarly
  * to EventBase, VirtualEventBase implements loopKeepAlive() functionality,
- * which allows callbacks holding LoopKeepAlive token to keep EventBase looping
+ * which allows callbacks holding KeepAlive token to keep EventBase looping
  * until they are complete.
  *
  * VirtualEventBase destructor blocks until all its KeepAliveTokens are released
@@ -41,7 +43,7 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager {
   VirtualEventBase(const VirtualEventBase&) = delete;
   VirtualEventBase& operator=(const VirtualEventBase&) = delete;
 
-  ~VirtualEventBase();
+  ~VirtualEventBase() override;
 
   EventBase& getEventBase() {
     return evb_;
@@ -59,14 +61,6 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager {
    */
   void runOnDestruction(EventBase::LoopCallback* callback);
 
-  /**
-   * @see EventBase::runInLoop
-   */
-  template <typename F>
-  void runInLoop(F&& f, bool thisIteration = false) {
-    evb_.runInLoop(std::forward<F>(f), thisIteration);
-  }
-
   /**
    * VirtualEventBase destructor blocks until all tasks scheduled through its
    * runInEventBaseThread are complete.
@@ -75,15 +69,19 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager {
    */
   template <typename F>
   void runInEventBaseThread(F&& f) {
-    // LoopKeepAlive token has to be released in the EventBase thread. If
-    // runInEventBaseThread() fails, we can't extract the LoopKeepAlive token
+    // KeepAlive token has to be released in the EventBase thread. If
+    // runInEventBaseThread() fails, we can't extract the KeepAlive token
     // from the callback to properly release it.
     CHECK(evb_.runInEventBaseThread([
-      keepAlive = loopKeepAliveAtomic(),
+      keepAliveToken = getKeepAliveToken(),
       f = std::forward<F>(f)
     ]() mutable { f(); }));
   }
 
+  HHWheelTimer& timer() {
+    return evb_.timer();
+  }
+
   void attachTimeoutManager(
       AsyncTimeout* obj,
       TimeoutManager::InternalEnum internal) override {
@@ -118,54 +116,61 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager {
     runInEventBaseThread(std::move(f));
   }
 
-  struct LoopKeepAliveDeleter {
-    void operator()(VirtualEventBase* evb) {
-      DCHECK(evb->getEventBase().inRunningEventBaseThread());
-      if (evb->loopKeepAliveCountAtomic_.load()) {
-        evb->loopKeepAliveCount_ += evb->loopKeepAliveCountAtomic_.exchange(0);
-      }
-      DCHECK(evb->loopKeepAliveCount_ > 0);
-      if (--evb->loopKeepAliveCount_ == 0) {
-        evb->loopKeepAliveBaton_.post();
-      }
-    }
-  };
-  using LoopKeepAlive = std::unique_ptr<VirtualEventBase, LoopKeepAliveDeleter>;
-
   /**
    * Returns you a handle which prevents VirtualEventBase from being destroyed.
-   * LoopKeepAlive handle can be released from EventBase loop only.
-   *
-   * loopKeepAlive() can be called from EventBase thread only.
+   * KeepAlive handle can be released from EventBase loop only.
    */
-  LoopKeepAlive loopKeepAlive() {
-    DCHECK(evb_.isInEventBaseThread());
-    ++loopKeepAliveCount_;
-    return LoopKeepAlive(this);
-  }
+  KeepAlive getKeepAliveToken() override {
+    DCHECK(loopKeepAliveCount_ + loopKeepAliveCountAtomic_.load() > 0);
 
-  /**
-   * Thread-safe version of loopKeepAlive()
-   */
-  LoopKeepAlive loopKeepAliveAtomic() {
     if (evb_.inRunningEventBaseThread()) {
-      return loopKeepAlive();
+      ++loopKeepAliveCount_;
+    } else {
+      ++loopKeepAliveCountAtomic_;
+    }
+    return makeKeepAlive();
+  }
+
+  bool inRunningEventBaseThread() const {
+    return evb_.inRunningEventBaseThread();
+  }
+
+ protected:
+  void keepAliveRelease() override {
+    DCHECK(getEventBase().isInEventBaseThread());
+    if (loopKeepAliveCountAtomic_.load()) {
+      loopKeepAliveCount_ += loopKeepAliveCountAtomic_.exchange(0);
+    }
+    DCHECK(loopKeepAliveCount_ > 0);
+    if (--loopKeepAliveCount_ == 0) {
+      destroyImpl();
     }
-    ++loopKeepAliveCountAtomic_;
-    return LoopKeepAlive(this);
   }
 
  private:
+  friend class EventBase;
+
+  ssize_t keepAliveCount() {
+    if (loopKeepAliveCountAtomic_.load()) {
+      loopKeepAliveCount_ += loopKeepAliveCountAtomic_.exchange(0);
+    }
+    return loopKeepAliveCount_;
+  }
+
+  std::future<void> destroy();
+  void destroyImpl();
+
   using LoopCallbackList = EventBase::LoopCallback::List;
 
   EventBase& evb_;
 
-  ssize_t loopKeepAliveCount_{0};
+  ssize_t loopKeepAliveCount_{1};
   std::atomic<ssize_t> loopKeepAliveCountAtomic_{0};
-  folly::Baton<> loopKeepAliveBaton_;
-  LoopKeepAlive loopKeepAlive_;
+  std::promise<void> destroyPromise_;
+  std::future<void> destroyFuture_{destroyPromise_.get_future()};
+  KeepAlive loopKeepAlive_{makeKeepAlive()};
 
-  EventBase::LoopKeepAlive evbLoopKeepAlive_;
+  KeepAlive evbLoopKeepAlive_;
 
   folly::Synchronized<LoopCallbackList> onDestructionCallbacks_;
 };