Commit 708e7e70 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Make keep-alive token a valid pointer for every Executor

Summary: This allows using a keep-alive token in places where Executor* was previously used.

Reviewed By: yfeldblum

Differential Revision: D7751516

fbshipit-source-id: af2cb31191a78306439408dbee78dcd923492e30
parent 772e5ce4
...@@ -27,13 +27,12 @@ void Executor::addWithPriority(Func, int8_t /* priority */) { ...@@ -27,13 +27,12 @@ void Executor::addWithPriority(Func, int8_t /* priority */) {
"addWithPriority() is not implemented for this Executor"); "addWithPriority() is not implemented for this Executor");
} }
void Executor::keepAliveAcquire() { bool Executor::keepAliveAcquire() {
LOG(FATAL) << __func__ << "() should not be called for folly::Executor types " return false;
<< "which do not override getKeepAliveToken()";
} }
void Executor::keepAliveRelease() { void Executor::keepAliveRelease() {
LOG(FATAL) << __func__ << "() should not be called for folly::Executor types " LOG(FATAL) << __func__ << "() should not be called for folly::Executor types "
<< "which do not override getKeepAliveToken()"; << "which do not override keepAliveAcquire()";
} }
} // namespace folly } // namespace folly
...@@ -49,7 +49,7 @@ class Executor { ...@@ -49,7 +49,7 @@ class Executor {
class KeepAlive { class KeepAlive {
public: public:
KeepAlive() {} KeepAlive() : executor_(nullptr, Deleter(true)) {}
void reset() { void reset() {
executor_.reset(); executor_.reset();
...@@ -65,31 +65,44 @@ class Executor { ...@@ -65,31 +65,44 @@ class Executor {
private: private:
friend class Executor; friend class Executor;
explicit KeepAlive(folly::Executor* executor) : executor_(executor) {} KeepAlive(folly::Executor* executor, bool dummy)
: executor_(executor, Deleter(dummy)) {}
struct Deleter { struct Deleter {
explicit Deleter(bool dummy) : dummy_(dummy) {}
void operator()(folly::Executor* executor) { void operator()(folly::Executor* executor) {
if (dummy_) {
return;
}
executor->keepAliveRelease(); executor->keepAliveRelease();
} }
private:
bool dummy_;
}; };
std::unique_ptr<folly::Executor, Deleter> executor_; std::unique_ptr<folly::Executor, Deleter> executor_;
}; };
/// Returns a keep-alive token which guarantees that Executor will keep /// Returns a keep-alive token which guarantees that Executor will keep
/// processing tasks until the token is released. /// processing tasks until the token is released (if supported by Executor).
/// /// KeepAlive always contains a valid pointer to an Executor.
/// If executor does not support keep-alive functionality - dummy token will KeepAlive getKeepAliveToken() {
/// be returned. if (keepAliveAcquire()) {
virtual KeepAlive getKeepAliveToken() { return makeKeepAlive();
return {}; }
return KeepAlive{this, true};
} }
protected: protected:
virtual void keepAliveAcquire(); // Acquire a keep alive token. Should return false if keep-alive mechanism
// is not supported.
virtual bool keepAliveAcquire();
// Release a keep alive token previously acquired by keepAliveAcquire().
// Will never be called if keepAliveAcquire() returns false.
virtual void keepAliveRelease(); virtual void keepAliveRelease();
KeepAlive makeKeepAlive() { KeepAlive makeKeepAlive() {
return KeepAlive{this}; return KeepAlive{this, false};
} }
}; };
......
...@@ -632,14 +632,6 @@ class EventBase : private boost::noncopyable, ...@@ -632,14 +632,6 @@ class EventBase : private boost::noncopyable,
// Implements the ScheduledExecutor interface // Implements the ScheduledExecutor interface
void scheduleAt(Func&& fn, TimePoint const& timeout) override; void scheduleAt(Func&& fn, TimePoint const& timeout) override;
/// 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.
KeepAlive getKeepAliveToken() override {
keepAliveAcquire();
return makeKeepAlive();
}
// TimeoutManager // TimeoutManager
void attachTimeoutManager( void attachTimeoutManager(
AsyncTimeout* obj, AsyncTimeout* obj,
...@@ -669,12 +661,13 @@ class EventBase : private boost::noncopyable, ...@@ -669,12 +661,13 @@ class EventBase : private boost::noncopyable,
EventBase* getEventBase() override; EventBase* getEventBase() override;
protected: protected:
void keepAliveAcquire() override { bool keepAliveAcquire() override {
if (inRunningEventBaseThread()) { if (inRunningEventBaseThread()) {
loopKeepAliveCount_++; loopKeepAliveCount_++;
} else { } else {
loopKeepAliveCountAtomic_.fetch_add(1, std::memory_order_relaxed); loopKeepAliveCountAtomic_.fetch_add(1, std::memory_order_relaxed);
} }
return true;
} }
void keepAliveRelease() override { void keepAliveRelease() override {
......
...@@ -116,20 +116,12 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager { ...@@ -116,20 +116,12 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager {
runInEventBaseThread(std::move(f)); runInEventBaseThread(std::move(f));
} }
/**
* Returns you a handle which prevents VirtualEventBase from being destroyed.
*/
KeepAlive getKeepAliveToken() override {
keepAliveAcquire();
return makeKeepAlive();
}
bool inRunningEventBaseThread() const { bool inRunningEventBaseThread() const {
return evb_.inRunningEventBaseThread(); return evb_.inRunningEventBaseThread();
} }
protected: protected:
void keepAliveAcquire() override { bool keepAliveAcquire() override {
DCHECK(loopKeepAliveCount_ + loopKeepAliveCountAtomic_.load() > 0); DCHECK(loopKeepAliveCount_ + loopKeepAliveCountAtomic_.load() > 0);
if (evb_.inRunningEventBaseThread()) { if (evb_.inRunningEventBaseThread()) {
...@@ -137,6 +129,7 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager { ...@@ -137,6 +129,7 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager {
} else { } else {
++loopKeepAliveCountAtomic_; ++loopKeepAliveCountAtomic_;
} }
return true;
} }
void keepAliveRelease() override { void keepAliveRelease() override {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment