Commit a6c3395f authored by Lee Howes's avatar Lee Howes Committed by Facebook Github Bot

Add thenExTry operation to support continuations taking executor parameter.

Summary: Adds the option of providing a continuation that takes an executor and a Try. This way an executor is always available to child tasks. Uses a separate thenExTry API to avoid potential overload set ambiguity.

Reviewed By: yfeldblum, andriigrynenko

Differential Revision: D14726443

fbshipit-source-id: ab635c502c8a010b9b68af38add86ff7c200ff38
parent ea225c31
...@@ -1094,6 +1094,24 @@ Future<T>::thenTry(F&& func) && { ...@@ -1094,6 +1094,24 @@ Future<T>::thenTry(F&& func) && {
return this->thenImplementation(std::move(lambdaFunc), R{}); return this->thenImplementation(std::move(lambdaFunc), R{});
} }
template <class T>
template <typename F>
Future<typename futures::detail::tryExecutorCallableResult<T, F>::value_type>
Future<T>::thenExTry(F&& func) && {
// As Futures may carry null executors, ensure that what we pass into the
// continuation is always usable by replacing with inline if necessary.
auto ka = getKeepAliveToken(this->getExecutor());
// Enforce that executor cannot be null
DCHECK(ka);
auto lambdaFunc = [f = std::forward<F>(func),
exec = std::move(ka)](folly::Try<T>&& t) mutable {
return std::forward<F>(f)(exec, std::move(t));
};
using R = futures::detail::tryCallableResult<T, decltype(lambdaFunc)>;
return this->thenImplementation(std::move(lambdaFunc), R{});
}
template <class T> template <class T>
template <typename F> template <typename F>
Future<typename futures::detail::valueCallableResult<T, F>::value_type> Future<typename futures::detail::valueCallableResult<T, F>::value_type>
......
...@@ -1261,6 +1261,10 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -1261,6 +1261,10 @@ class Future : private futures::detail::FutureBase<T> {
Future<typename futures::detail::tryCallableResult<T, F>::value_type> thenTry( Future<typename futures::detail::tryCallableResult<T, F>::value_type> thenTry(
F&& func) &&; F&& func) &&;
template <typename F>
Future<typename futures::detail::tryExecutorCallableResult<T, F>::value_type>
thenExTry(F&& func) &&;
template <typename R, typename... Args> template <typename R, typename... Args>
auto thenTry(R (&func)(Args...)) && { auto thenTry(R (&func)(Args...)) && {
return std::move(*this).thenTry(&func); return std::move(*this).thenTry(&func);
......
...@@ -1029,6 +1029,15 @@ TEST(Future, thenTry) { ...@@ -1029,6 +1029,15 @@ TEST(Future, thenTry) {
EXPECT_TRUE(f.isReady()); EXPECT_TRUE(f.isReady());
} }
TEST(Future, ThenTryWithExecutor) {
ManualExecutor executor;
auto sf = makeFuture().via(&executor).thenExTry(
[&](const Executor::KeepAlive<>& e, Try<Unit>) {
EXPECT_EQ(&executor, e.get());
});
std::move(sf).getVia(&executor);
}
TEST(Future, thenValue) { TEST(Future, thenValue) {
bool flag = false; bool flag = false;
makeFuture<int>(42).thenValue([&](int i) { makeFuture<int>(42).thenValue([&](int i) {
......
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