Commit 4c132efd authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Remove priority from Core

Summary: Wrap Executor in ExecutorWithPriority if custom priority is passed.

Reviewed By: yfeldblum

Differential Revision: D14079222

fbshipit-source-id: 56917827f54115b90ca237c71321f7db327355e1
parent cd6352dd
......@@ -21,6 +21,7 @@
#include <thread>
#include <folly/Optional.h>
#include <folly/executors/ExecutorWithPriority.h>
#include <folly/executors/InlineExecutor.h>
#include <folly/executors/QueuedImmediateExecutor.h>
#include <folly/futures/detail/Core.h>
......@@ -853,9 +854,7 @@ SemiFuture<T>& SemiFuture<T>::operator=(Future<T>&& other) noexcept {
}
template <class T>
Future<T> SemiFuture<T>::via(
Executor::KeepAlive<> executor,
int8_t priority) && {
Future<T> SemiFuture<T>::via(Executor::KeepAlive<> executor) && {
if (!executor) {
throw_exception<FutureNoExecutor>();
}
......@@ -866,11 +865,19 @@ Future<T> SemiFuture<T>::via(
auto newFuture = Future<T>(this->core_);
this->core_ = nullptr;
newFuture.setExecutor(std::move(executor), priority);
newFuture.setExecutor(std::move(executor));
return newFuture;
}
template <class T>
Future<T> SemiFuture<T>::via(
Executor::KeepAlive<> executor,
int8_t priority) && {
return std::move(*this).via(
ExecutorWithPriority::create(std::move(executor), priority));
}
template <class T>
Future<T> SemiFuture<T>::toUnsafeFuture() && {
return std::move(*this).via(&InlineExecutor::instance());
......@@ -1029,8 +1036,8 @@ typename std::
}
template <class T>
Future<T> Future<T>::via(Executor::KeepAlive<> executor, int8_t priority) && {
this->setExecutor(std::move(executor), priority);
Future<T> Future<T>::via(Executor::KeepAlive<> executor) && {
this->setExecutor(std::move(executor));
auto newFuture = Future<T>(this->core_);
this->core_ = nullptr;
......@@ -1038,7 +1045,13 @@ Future<T> Future<T>::via(Executor::KeepAlive<> executor, int8_t priority) && {
}
template <class T>
Future<T> Future<T>::via(Executor::KeepAlive<> executor, int8_t priority) & {
Future<T> Future<T>::via(Executor::KeepAlive<> executor, int8_t priority) && {
return std::move(*this).via(
ExecutorWithPriority::create(std::move(executor), priority));
}
template <class T>
Future<T> Future<T>::via(Executor::KeepAlive<> executor) & {
this->throwIfInvalid();
Promise<T> p;
auto sf = p.getSemiFuture();
......@@ -1052,7 +1065,12 @@ Future<T> Future<T>::via(Executor::KeepAlive<> executor, int8_t priority) & {
// check in SemiFuture::via
auto f = Future<T>(sf.core_);
sf.core_ = nullptr;
return std::move(f).via(std::move(executor), priority);
return std::move(f).via(std::move(executor));
}
template <class T>
Future<T> Future<T>::via(Executor::KeepAlive<> executor, int8_t priority) & {
return this->via(ExecutorWithPriority::create(std::move(executor), priority));
}
template <typename T>
......@@ -1388,6 +1406,10 @@ Future<T> makeFuture(Try<T> t) {
}
// via
Future<Unit> via(Executor::KeepAlive<> executor) {
return makeFuture().via(std::move(executor));
}
Future<Unit> via(Executor::KeepAlive<> executor, int8_t priority) {
return makeFuture().via(std::move(executor), priority);
}
......
......@@ -344,11 +344,6 @@ class FutureBase {
raise(FutureCancellation());
}
// Returns this future's executor priority.
int8_t getPriority() const {
return getCore().getPriority();
}
protected:
friend class Promise<T>;
template <class>
......@@ -417,10 +412,8 @@ class FutureBase {
// Must be called either before attaching a callback or after the callback
// has already been invoked, but not concurrently with anything which might
// trigger invocation of the callback.
void setExecutor(
Executor::KeepAlive<> x,
int8_t priority = Executor::MID_PRI) {
getCore().setExecutor(std::move(x), priority);
void setExecutor(Executor::KeepAlive<> x) {
getCore().setExecutor(std::move(x));
}
// Variant: returns a value
......@@ -551,7 +544,6 @@ class SemiFuture : private futures::detail::FutureBase<T> {
/* implicit */ SemiFuture(Future<T>&&) noexcept;
using Base::cancel;
using Base::getPriority;
using Base::hasException;
using Base::hasValue;
using Base::isReady;
......@@ -665,9 +657,8 @@ class SemiFuture : private futures::detail::FutureBase<T> {
bool wait(Duration dur) &&;
/// Returns a Future which will call back on the other side of executor.
Future<T> via(
Executor::KeepAlive<> executor,
int8_t priority = Executor::MID_PRI) &&;
Future<T> via(Executor::KeepAlive<> executor) &&;
Future<T> via(Executor::KeepAlive<> executor, int8_t priority) &&;
/// Defer work to run on the consumer of the future.
/// Function must take a Try as a parameter.
......@@ -1008,7 +999,6 @@ class Future : private futures::detail::FutureBase<T> {
Future& operator=(Future<T2>&&);
using Base::cancel;
using Base::getPriority;
using Base::hasException;
using Base::hasValue;
using Base::isReady;
......@@ -1082,9 +1072,8 @@ class Future : private futures::detail::FutureBase<T> {
///
/// - `valid() == false`
/// - `RESULT.valid() == true`
Future<T> via(
Executor::KeepAlive<> executor,
int8_t priority = Executor::MID_PRI) &&;
Future<T> via(Executor::KeepAlive<> executor) &&;
Future<T> via(Executor::KeepAlive<> executor, int8_t priority) &&;
/// Returns a Future which will call back on the other side of executor.
///
......@@ -1099,9 +1088,8 @@ class Future : private futures::detail::FutureBase<T> {
/// - `valid() == true`
/// - `RESULT.valid() == true`
/// - when `this` gets fulfilled, it automatically fulfills RESULT
Future<T> via(
Executor::KeepAlive<> executor,
int8_t priority = Executor::MID_PRI) &;
Future<T> via(Executor::KeepAlive<> executor) &;
Future<T> via(Executor::KeepAlive<> executor, int8_t priority) &;
/// When this Future has completed, execute func which is a function that
/// can be called with either `T&&` or `Try<T>&&`.
......
......@@ -51,8 +51,7 @@ class FutureSplitter {
*/
explicit FutureSplitter(Future<T>&& future)
: promise_(std::make_shared<SharedPromise<T>>()),
e_(getExecutorFrom(future)),
priority_(future.getPriority()) {
e_(getExecutorFrom(future)) {
std::move(future).thenTry([promise = promise_](Try<T>&& theTry) {
promise->setTry(std::move(theTry));
});
......@@ -65,7 +64,7 @@ class FutureSplitter {
if (promise_ == nullptr) {
throw_exception<FutureSplitterInvalid>();
}
return promise_->getSemiFuture().via(e_, priority_);
return promise_->getSemiFuture().via(e_);
}
/**
......@@ -81,7 +80,6 @@ class FutureSplitter {
private:
std::shared_ptr<SharedPromise<T>> promise_;
Executor* e_ = nullptr;
int8_t priority_{-1};
static Executor* getExecutorFrom(Future<T>& f) {
// If the passed future had a null executor, use an inline executor
......
......@@ -421,26 +421,15 @@ class Core final {
/// Call only from consumer thread, either before attaching a callback or
/// after the callback has already been invoked, but not concurrently with
/// anything which might trigger invocation of the callback.
void setExecutor(
Executor::KeepAlive<> x,
int8_t priority = Executor::MID_PRI) {
void setExecutor(Executor::KeepAlive<> x) {
DCHECK(state_ != State::OnlyCallback);
executor_ = std::move(x);
priority_ = priority;
}
void setExecutor(Executor* x, int8_t priority = Executor::MID_PRI) {
setExecutor(getKeepAliveToken(x), priority);
}
Executor* getExecutor() const {
return executor_.get();
}
int8_t getPriority() const {
return priority_;
}
/// Call only from consumer thread
///
/// Eventual effect is to pass `e` to the Promise's interrupt handler, either
......@@ -572,7 +561,6 @@ class Core final {
if (executor_) {
auto x = exchange(executor_, Executor::KeepAlive<>());
int8_t priority = priority_;
exception_wrapper ew;
// We need to reset `callback_` after it was executed (which can happen
......@@ -590,25 +578,13 @@ class Core final {
CoreAndCallbackReference guard_lambda(this);
try {
auto xPtr = x.get();
if (LIKELY(x->getNumPriorities() == 1)) {
xPtr->add([core_ref = std::move(guard_lambda),
keepAlive = std::move(x)]() mutable {
auto cr = std::move(core_ref);
Core* const core = cr.getCore();
RequestContextScopeGuard rctx(core->context_);
core->callback_(std::move(core->result_));
});
} else {
xPtr->addWithPriority(
[core_ref = std::move(guard_lambda),
keepAlive = std::move(x)]() mutable {
auto cr = std::move(core_ref);
Core* const core = cr.getCore();
RequestContextScopeGuard rctx(core->context_);
core->callback_(std::move(core->result_));
},
priority);
}
xPtr->add([core_ref = std::move(guard_lambda),
keepAlive = std::move(x)]() mutable {
auto cr = std::move(core_ref);
Core* const core = cr.getCore();
RequestContextScopeGuard rctx(core->context_);
core->callback_(std::move(core->result_));
});
} catch (const std::exception& e) {
ew = exception_wrapper(std::current_exception(), e);
} catch (...) {
......@@ -633,7 +609,7 @@ class Core final {
void proxyCallback() {
state_.store(State::Empty, std::memory_order_relaxed);
proxy_->setExecutor(std::move(executor_), priority_);
proxy_->setExecutor(std::move(executor_));
proxy_->setCallback(std::move(callback_), std::move(context_));
proxy_->detachFuture();
context_.~Context();
......@@ -673,7 +649,6 @@ class Core final {
std::atomic<unsigned char> callbackReferences_{0};
std::atomic<bool> interruptHandlerSet_{false};
SpinLock interruptLock_;
int8_t priority_{-1};
Executor::KeepAlive<> executor_;
union {
Context context_;
......
......@@ -315,9 +315,8 @@ Future<T> makeFuture(Try<T> t);
*
* @returns a void Future that will call back on the given executor
*/
inline Future<Unit> via(
Executor::KeepAlive<> executor,
int8_t priority = Executor::MID_PRI);
inline Future<Unit> via(Executor::KeepAlive<> executor);
inline Future<Unit> via(Executor::KeepAlive<> executor, int8_t priority);
/// Execute a function via the given executor and return a future.
/// This is semantically equivalent to via(executor).then(func), but
......
......@@ -174,19 +174,3 @@ TEST(FutureSplitter, splitFutureFailure) {
EXPECT_TRUE(f2.isReady());
EXPECT_TRUE(f2.hasException());
}
TEST(FutureSplitter, splitFuturePriority) {
std::vector<int8_t> priorities = {
folly::Executor::LO_PRI,
folly::Executor::MID_PRI,
folly::Executor::HI_PRI,
};
for (const auto priority : priorities) {
Promise<int> p;
folly::FutureSplitter<int> sp(
p.getSemiFuture().via(&InlineExecutor::instance(), priority));
auto fut = sp.getFuture();
EXPECT_EQ(priority, fut.getPriority());
}
}
......@@ -195,7 +195,9 @@ TEST(Via, chain3) {
}
struct PriorityExecutor : public Executor {
void add(Func /* f */) override {}
void add(Func /* f */) override {
count1++;
}
void addWithPriority(Func f, int8_t priority) override {
int mid = getNumPriorities() / 2;
......
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