#include <boost/intrusive/list.hpp>
#include <boost/utility.hpp>
+#include <folly/CallOnce.h>
#include <folly/Executor.h>
#include <folly/Function.h>
#include <folly/Portability.h>
#include <folly/io/async/HHWheelTimer.h>
#include <folly/io/async/Request.h>
#include <folly/io/async/TimeoutManager.h>
+#include <folly/portability/Event.h>
#include <glog/logging.h>
-#include <event.h> // libevent
namespace folly {
* observer, max latency and avg loop time.
*/
explicit EventBase(event_base* evb, bool enableTimeMeasurement = true);
- ~EventBase();
+ ~EventBase() override;
/**
* Runs the event loop.
std::this_thread::get_id();
}
+ /**
+ * Equivalent to CHECK(isInEventBaseThread()) (and assert/DCHECK for
+ * dcheckIsInEventBaseThread), but it prints more information on
+ * failure.
+ */
+ void checkIsInEventBaseThread() const;
+ void dcheckIsInEventBaseThread() const {
+ if (kIsDebug) {
+ checkIsInEventBaseThread();
+ }
+ }
+
HHWheelTimer& timer() {
if (!wheelTimer_) {
wheelTimer_ = HHWheelTimer::newTimer(this);
* first handler fired within that cycle.
*
*/
- void bumpHandlingTime() override final;
+ void bumpHandlingTime() final;
class SmoothLoopTime {
public:
loopOnce();
}
- struct LoopKeepAliveDeleter {
- void operator()(EventBase* evb) {
- DCHECK(evb->isInEventBaseThread());
- evb->loopKeepAliveCount_--;
- }
- };
- using LoopKeepAlive = std::unique_ptr<EventBase, LoopKeepAliveDeleter>;
-
/// Returns you a handle which make loop() behave like loopForever() until
/// destroyed. loop() will return to its original behavior only when all
/// loop keep-alives are released. Loop holder is safe to release only from
/// EventBase thread.
- ///
- /// May return no op LoopKeepAlive if loopForever() is already running.
- LoopKeepAlive loopKeepAlive() {
- DCHECK(isInEventBaseThread());
- loopKeepAliveCount_++;
- return LoopKeepAlive(this);
- }
-
- // Thread-safe version of loopKeepAlive()
- LoopKeepAlive loopKeepAliveAtomic() {
+ KeepAlive getKeepAliveToken() override {
if (inRunningEventBaseThread()) {
- return loopKeepAlive();
+ loopKeepAliveCount_++;
+ } else {
+ loopKeepAliveCountAtomic_.fetch_add(1, std::memory_order_relaxed);
}
- loopKeepAliveCountAtomic_.fetch_add(1, std::memory_order_relaxed);
- return LoopKeepAlive(this);
+ return makeKeepAlive();
}
// TimeoutManager
void attachTimeoutManager(
AsyncTimeout* obj,
- TimeoutManager::InternalEnum internal) override final;
+ TimeoutManager::InternalEnum internal) final;
- void detachTimeoutManager(AsyncTimeout* obj) override final;
+ void detachTimeoutManager(AsyncTimeout* obj) final;
bool scheduleTimeout(AsyncTimeout* obj, TimeoutManager::timeout_type timeout)
- override final;
+ final;
- void cancelTimeout(AsyncTimeout* obj) override final;
+ void cancelTimeout(AsyncTimeout* obj) final;
- bool isInTimeoutManagerThread() override final {
+ bool isInTimeoutManagerThread() final {
return isInEventBaseThread();
}
+ // Returns a VirtualEventBase attached to this EventBase. Can be used to
+ // pass to APIs which expect VirtualEventBase. This VirtualEventBase will be
+ // destroyed together with the EventBase.
+ //
+ // Any number of VirtualEventBases instances may be independently constructed,
+ // which are backed by this EventBase. This method should be only used if you
+ // don't need to manage the life time of the VirtualEventBase used.
+ folly::VirtualEventBase& getVirtualEventBase();
+
+ protected:
+ void keepAliveRelease() override {
+ dcheckIsInEventBaseThread();
+ loopKeepAliveCount_--;
+ }
+
private:
void applyLoopKeepAlive();
// see EventBaseLocal
friend class detail::EventBaseLocalBase;
template <typename T> friend class EventBaseLocal;
- std::mutex localStorageMutex_;
std::unordered_map<uint64_t, std::shared_ptr<void>> localStorage_;
std::unordered_set<detail::EventBaseLocalBaseBase*> localStorageToDtor_;
+
+ folly::once_flag virtualEventBaseInitFlag_;
+ std::unique_ptr<VirtualEventBase> virtualEventBase_;
};
template <typename T>