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

Support inline defer 5/n - Make defer use inline forms of then internally

Summary: Defer uses inline continuations by default, if bound executors match.

Reviewed By: andriigrynenko

Differential Revision: D15300706

fbshipit-source-id: fc17c70ed9956442007a1cc2f6a082f75c555ad4
parent ea6ee538
......@@ -823,7 +823,7 @@ SemiFuture<T>::defer(F&& func) && {
}
}();
auto sf = Future<T>(this->core_).thenTry(std::forward<F>(func)).semi();
auto sf = Future<T>(this->core_).thenTryInline(std::forward<F>(func)).semi();
this->core_ = nullptr;
// Carry deferred executor through chain as constructor from Future will
// nullify it
......@@ -849,9 +849,9 @@ SemiFuture<T>::deferExTry(F&& func) && {
}();
auto sf = Future<T>(this->core_)
.thenExTry([func = std::forward<F>(func)](
folly::Executor::KeepAlive<>&& keepAlive,
folly::Try<T>&& val) mutable {
.thenExTryInline([func = std::forward<F>(func)](
folly::Executor::KeepAlive<>&& keepAlive,
folly::Try<T>&& val) mutable {
return std::forward<F>(func)(
std::move(keepAlive), std::forward<decltype(val)>(val));
})
......
......@@ -666,6 +666,11 @@ class SemiFuture : private futures::detail::FutureBase<T> {
/// support all executors would boost block and we would simply use some form
/// of driveable executor here.
///
/// All forms of defer will run the continuation inline with the execution of
/// the previous callback in the chain if the callback attached to the
/// previous future that triggers execution of func runs on the same executor
/// that func would be executed on.
///
/// Preconditions:
///
/// - `valid() == true` (else throws FutureInvalid)
......@@ -690,6 +695,11 @@ class SemiFuture : private futures::detail::FutureBase<T> {
/// Defer for functions taking a T rather than a Try<T>.
///
/// All forms of defer will run the continuation inline with the execution of
/// the previous callback in the chain if the callback attached to the
/// previous future that triggers execution of func runs on the same executor
/// that func would be executed on.
///
/// Preconditions:
///
/// - `valid() == true` (else throws FutureInvalid)
......
......@@ -249,7 +249,8 @@ TEST(Via, then2) {
TEST(Via, allowInline) {
ManualExecutor x1, x2;
bool a = false, b = false, c = false, d = false, e = false, f = false,
g = false, h = false, i = false, j = false, k = false, l = false;
g = false, h = false, i = false, j = false, k = false, l = false,
m = false, n = false, o = false, p = false, q = false, r = false;
via(&x1)
.thenValue([&](auto&&) { a = true; })
.thenTryInline([&](auto&&) { b = true; })
......@@ -269,7 +270,19 @@ TEST(Via, allowInline) {
.semi()
.deferValue([&](auto&&) { k = true; })
.via(&x2)
.thenValueInline([&](auto&&) { l = true; });
.thenValueInline([&](auto&&) { l = true; })
.semi()
.deferValue([&](auto&&) { m = true; })
.via(&x1)
.thenValue([&](auto&&) { n = true; })
.semi()
.deferValue([&](auto&&) { o = true; })
.deferValue([&](auto&&) { p = true; })
.via(&x1)
.semi()
.deferValue([&](auto&&) { q = true; })
.deferValue([&](auto&&) { r = true; })
.via(&x2);
EXPECT_FALSE(a);
EXPECT_FALSE(b);
......@@ -311,16 +324,31 @@ TEST(Via, allowInline) {
EXPECT_TRUE(i);
EXPECT_FALSE(j);
// Deferred work is not inline so k will remain false
// Defer should run on x1 and therefore not inline
// Subsequent deferred work is run on x1 and hence not inlined.
x2.run();
EXPECT_TRUE(j);
EXPECT_FALSE(k);
// Deferred work is not inline, but subsequent inline work should be inlined
// consistently with deferred work.
x2.run();
EXPECT_TRUE(k);
EXPECT_TRUE(l);
EXPECT_FALSE(m);
// Complete the deferred task
x1.run();
EXPECT_TRUE(m);
EXPECT_FALSE(n);
// Here defer and the above thenValue are both on x1, defer should be
// inline
x1.run();
EXPECT_TRUE(n);
EXPECT_TRUE(o);
EXPECT_TRUE(p);
EXPECT_FALSE(q);
// Change of executor in deferred executor so now run x2 to complete
x2.run();
EXPECT_TRUE(q);
EXPECT_TRUE(r);
}
#ifndef __APPLE__ // TODO #7372389
......
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