Copyright 2014->2015
[folly.git] / folly / io / async / EventBase.h
index 109da17cc5839c319ce3df3be1e305b1c07b6cb2..ca895c3a5025e5460e6ccaff5801ad75f7b72389 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
 #include <folly/io/async/TimeoutManager.h>
 #include <folly/io/async/Request.h>
 #include <folly/Executor.h>
+#include <folly/futures/DrivableExecutor.h>
 #include <memory>
 #include <stack>
 #include <list>
@@ -95,9 +96,9 @@ class RequestEventBase : public RequestData {
  * EventBase from other threads.  When it is safe to call a method from
  * another thread it is explicitly listed in the method comments.
  */
-class EventBase :
-  private boost::noncopyable, public TimeoutManager, public Executor
-{
+class EventBase : private boost::noncopyable,
+                  public TimeoutManager,
+                  public DrivableExecutor {
  public:
   /**
    * A callback interface to use with runInLoop()
@@ -142,8 +143,14 @@ class EventBase :
 
   /**
    * Create a new EventBase object.
+   *
+   * @param enableTimeMeasurement Informs whether this event base should measure
+   *                              time. Disabling it would likely improve
+   *                              performance, but will disable some features
+   *                              that relies on time-measurement, including:
+   *                              observer, max latency and avg loop time.
    */
-  EventBase();
+  explicit EventBase(bool enableTimeMeasurement = true);
 
   /**
    * Create a new EventBase object that will use the specified libevent
@@ -151,8 +158,14 @@ class EventBase :
    *
    * The EventBase will take ownership of this event_base, and will call
    * event_base_free(evb) when the EventBase is destroyed.
+   *
+   * @param enableTimeMeasurement Informs whether this event base should measure
+   *                              time. Disabling it would likely improve
+   *                              performance, but will disable some features
+   *                              that relies on time-measurement, including:
+   *                              observer, max latency and avg loop time.
    */
-  explicit EventBase(event_base* evb);
+  explicit EventBase(event_base* evb, bool enableTimeMeasurement = true);
   ~EventBase();
 
   /**
@@ -345,26 +358,64 @@ class EventBase :
    */
   bool runInEventBaseThread(const Cob& fn);
 
+  /*
+   * Like runInEventBaseThread, but the caller waits for the callback to be
+   * executed.
+   */
+  template<typename T>
+  bool runInEventBaseThreadAndWait(void (*fn)(T*), T* arg) {
+    return runInEventBaseThreadAndWait(reinterpret_cast<void (*)(void*)>(fn),
+                                       reinterpret_cast<void*>(arg));
+  }
+
+  /*
+   * Like runInEventBaseThread, but the caller waits for the callback to be
+   * executed.
+   */
+  bool runInEventBaseThreadAndWait(void (*fn)(void*), void* arg) {
+    return runInEventBaseThreadAndWait(std::bind(fn, arg));
+  }
+
+  /*
+   * Like runInEventBaseThread, but the caller waits for the callback to be
+   * executed.
+   */
+  bool runInEventBaseThreadAndWait(const Cob& fn);
+
   /**
    * Runs the given Cob at some time after the specified number of
    * milliseconds.  (No guarantees exactly when.)
    *
-   * @return  true iff the cob was successfully registered.
+   * Throws a std::system_error if an error occurs.
    */
-  bool runAfterDelay(
+  void runAfterDelay(
       const Cob& c,
       int milliseconds,
-      TimeoutManager::InternalEnum = TimeoutManager::InternalEnum::NORMAL);
+      TimeoutManager::InternalEnum in = TimeoutManager::InternalEnum::NORMAL);
+
+  /**
+   * @see tryRunAfterDelay for more details
+   *
+   * @return  true iff the cob was successfully registered.
+   *
+   * */
+  bool tryRunAfterDelay(
+      const Cob& cob,
+      int milliseconds,
+      TimeoutManager::InternalEnum in = TimeoutManager::InternalEnum::NORMAL);
 
   /**
    * Set the maximum desired latency in us and provide a callback which will be
    * called when that latency is exceeded.
+   * OBS: This functionality depends on time-measurement.
    */
   void setMaxLatency(int64_t maxLatency, const Cob& maxLatencyCob) {
+    assert(enableTimeMeasurement_);
     maxLatency_ = maxLatency;
     maxLatencyCob_ = maxLatencyCob;
   }
 
+
   /**
    * Set smoothing coefficient for loop load average; # of milliseconds
    * for exp(-1) (1/2.71828...) decay.
@@ -380,6 +431,7 @@ class EventBase :
    * Get the average loop time in microseconds (an exponentially-smoothed ave)
    */
   double getAvgLoopTime() const {
+    assert(enableTimeMeasurement_);
     return avgLoopTime_.get();
   }
 
@@ -429,7 +481,7 @@ class EventBase :
    * first handler fired within that cycle.
    *
    */
-  bool bumpHandlingTime();
+  bool bumpHandlingTime() override;
 
   class SmoothLoopTime {
    public:
@@ -459,8 +511,8 @@ class EventBase :
     int64_t oldBusyLeftover_;
   };
 
-  void setObserver(
-    const std::shared_ptr<EventBaseObserver>& observer) {
+  void setObserver(const std::shared_ptr<EventBaseObserver>& observer) {
+    assert(enableTimeMeasurement_);
     observer_ = observer;
   }
 
@@ -485,19 +537,25 @@ class EventBase :
     runInEventBaseThread(fn);
   }
 
+  /// Implements the DrivableExecutor interface
+  void drive() override {
+    loopOnce();
+  }
+
  private:
 
   // TimeoutManager
   void attachTimeoutManager(AsyncTimeout* obj,
-                            TimeoutManager::InternalEnum internal);
+                            TimeoutManager::InternalEnum internal) override;
 
-  void detachTimeoutManager(AsyncTimeout* obj);
+  void detachTimeoutManager(AsyncTimeout* obj) override;
 
-  bool scheduleTimeout(AsyncTimeout* obj, std::chrono::milliseconds timeout);
+  bool scheduleTimeout(AsyncTimeout* obj, std::chrono::milliseconds timeout)
+    override;
 
-  void cancelTimeout(AsyncTimeout* obj);
+  void cancelTimeout(AsyncTimeout* obj) override;
 
-  bool isInTimeoutManagerThread() {
+  bool isInTimeoutManagerThread() override {
     return isInEventBaseThread();
   }
 
@@ -601,6 +659,11 @@ class EventBase :
   // callback called when latency limit is exceeded
   Cob maxLatencyCob_;
 
+  // Enables/disables time measurements in loopBody(). if disabled, the
+  // following functionality that relies on time-measurement, will not
+  // be supported: avg loop time, observer and max latency.
+  const bool enableTimeMeasurement_;
+
   // we'll wait this long before running deferred callbacks if the event
   // loop is idle.
   static const int kDEFAULT_IDLE_WAIT_USEC = 20000; // 20ms