Commit cd338595 authored by Hans Fugal's avatar Hans Fugal Committed by Alecs King

then-with-Executor

Summary:
Pass an Executor to `then`, which applies only for that callback. This is on
the one hand just a convenience method, but it's a major convenience when it's
needed, because grabbing, storing, and restoring the old Executor in the
middle of a chain is very inconvenient indeed.

Test Plan:
new unit
docblock comments

Reviewed By: jsedgwick@fb.com

Subscribers: folly-diffs@, davejwatson, chalfant, yfeldblum, nkgupta, jsedgwick, exa, robbert

FB internal diff: D2011542

Tasks: 6771589, 6838553

Signature: t1:2011542:1429660204:f5959b1e0b3b36dfb8c3c7091302d19101dde93b
parent 23bf239f
...@@ -235,6 +235,19 @@ Future<T>::then(R(Caller::*func)(Args...), Caller *instance) { ...@@ -235,6 +235,19 @@ Future<T>::then(R(Caller::*func)(Args...), Caller *instance) {
}); });
} }
// TODO(6838553)
#ifndef __clang__
template <class T>
template <class... Args>
auto Future<T>::then(Executor* x, Args&&... args)
-> decltype(this->then(std::forward<Args>(args)...))
{
auto oldX = getExecutor();
setExecutor(x);
return this->then(std::forward<Args>(args)...).via(oldX);
}
#endif
template <class T> template <class T>
Future<void> Future<T>::then() { Future<void> Future<T>::then() {
return then([] (Try<T>&& t) {}); return then([] (Try<T>&& t) {});
......
...@@ -335,6 +335,25 @@ class Future { ...@@ -335,6 +335,25 @@ class Future {
Future<typename isFuture<R>::Inner> Future<typename isFuture<R>::Inner>
then(R(Caller::*func)(Args...), Caller *instance); then(R(Caller::*func)(Args...), Caller *instance);
// TODO(6838553)
#ifndef __clang__
/// Execute the callback via the given Executor. The executor doesn't stick.
///
/// Contrast
///
/// f.via(x).then(b).then(c)
///
/// with
///
/// f.then(x, b).then(c)
///
/// In the former both b and c execute via x. In the latter, only b executes
/// via x, and c executes via the same executor (if any) that f had.
template <class... Args>
auto then(Executor* x, Args&&... args)
-> decltype(this->then(std::forward<Args>(args)...));
#endif
/// Convenience method for ignoring the value and creating a Future<void>. /// Convenience method for ignoring the value and creating a Future<void>.
/// Exceptions still propagate. /// Exceptions still propagate.
Future<void> then(); Future<void> then();
......
...@@ -184,3 +184,36 @@ TEST(Via, chain3) { ...@@ -184,3 +184,36 @@ TEST(Via, chain3) {
EXPECT_EQ(42, f.get()); EXPECT_EQ(42, f.get());
EXPECT_EQ(3, count); EXPECT_EQ(3, count);
} }
// TODO(6838553)
#ifndef __clang__
TEST(Via, then2) {
ManualExecutor x1, x2;
bool a,b,c;
via(&x1)
.then([&]{ a = true; })
.then(&x2, [&]{ b = true; })
.then([&]{ c = true; });
EXPECT_FALSE(a);
EXPECT_FALSE(b);
x1.run();
EXPECT_TRUE(a);
EXPECT_FALSE(b);
EXPECT_FALSE(c);
x2.run();
EXPECT_TRUE(b);
EXPECT_FALSE(c);
x1.run();
EXPECT_TRUE(c);
}
TEST(Via, then2Variadic) {
struct Foo { void foo(Try<void>) {} };
Foo f;
makeFuture().then(nullptr, &Foo::foo, &f);
}
#endif
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