/*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2016-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#pragma once
-#include <folly/Baton.h>
+#include <future>
+
#include <folly/Executor.h>
#include <folly/io/async/EventBase.h>
+#include <folly/synchronization/Baton.h>
namespace folly {
VirtualEventBase(const VirtualEventBase&) = delete;
VirtualEventBase& operator=(const VirtualEventBase&) = delete;
- ~VirtualEventBase();
+ ~VirtualEventBase() override;
EventBase& getEventBase() {
return evb_;
*/
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.
/**
* Returns you a handle which prevents VirtualEventBase from being destroyed.
- * KeepAlive handle can be released from EventBase loop only.
*/
KeepAlive getKeepAliveToken() override {
- if (evb_.inRunningEventBaseThread()) {
- ++loopKeepAliveCount_;
- } else {
- ++loopKeepAliveCountAtomic_;
- }
+ keepAliveAcquire();
return makeKeepAlive();
}
}
protected:
+ void keepAliveAcquire() override {
+ DCHECK(loopKeepAliveCount_ + loopKeepAliveCountAtomic_.load() > 0);
+
+ if (evb_.inRunningEventBaseThread()) {
+ ++loopKeepAliveCount_;
+ } else {
+ ++loopKeepAliveCountAtomic_;
+ }
+ }
+
void keepAliveRelease() override {
- DCHECK(getEventBase().inRunningEventBaseThread());
+ if (!evb_.inRunningEventBaseThread()) {
+ return evb_.add([=] { keepAliveRelease(); });
+ }
if (loopKeepAliveCountAtomic_.load()) {
loopKeepAliveCount_ += loopKeepAliveCountAtomic_.exchange(0);
}
DCHECK(loopKeepAliveCount_ > 0);
if (--loopKeepAliveCount_ == 0) {
- loopKeepAliveBaton_.post();
+ destroyImpl();
}
}
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_;
- KeepAlive loopKeepAlive_;
+ std::promise<void> destroyPromise_;
+ std::future<void> destroyFuture_{destroyPromise_.get_future()};
+ KeepAlive loopKeepAlive_{makeKeepAlive()};
KeepAlive evbLoopKeepAlive_;
folly::Synchronized<LoopCallbackList> onDestructionCallbacks_;
};
-}
+} // namespace folly