/*
- * 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.
#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>
* 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()
/**
* 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
*
* 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();
/**
*/
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.
* Get the average loop time in microseconds (an exponentially-smoothed ave)
*/
double getAvgLoopTime() const {
+ assert(enableTimeMeasurement_);
return avgLoopTime_.get();
}
* first handler fired within that cycle.
*
*/
- bool bumpHandlingTime();
+ bool bumpHandlingTime() override;
class SmoothLoopTime {
public:
int64_t oldBusyLeftover_;
};
- void setObserver(
- const std::shared_ptr<EventBaseObserver>& observer) {
+ void setObserver(const std::shared_ptr<EventBaseObserver>& observer) {
+ assert(enableTimeMeasurement_);
observer_ = observer;
}
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();
}
// 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