Commit 446a5a23 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Fix FutureAwaitable to work with tail-call optimization

Summary: setCallback_ is an internal API that doesn't provide a guarantee that when the callback is run the Try will be stored inside of the original future. Thus the Try should be moved by the callback instead.

Reviewed By: LeeHowes

Differential Revision: D13793991

fbshipit-source-id: 1e8c4e423b8e1786099cae84bd99ac350c32d937
parent e66fcd54
...@@ -297,4 +297,18 @@ TEST(Task, RequestContextSideEffectsArePreserved) { ...@@ -297,4 +297,18 @@ TEST(Task, RequestContextSideEffectsArePreserved) {
EXPECT_FALSE(t.hasException()); EXPECT_FALSE(t.hasException());
} }
TEST(Task, FutureTailCall) {
folly::ManualExecutor executor;
EXPECT_EQ(
42,
folly::coro::co_invoke([&]() -> folly::coro::Task<int> {
co_return co_await folly::makeSemiFuture().deferValue(
[](auto) { return folly::makeSemiFuture(42); });
})
.scheduleOn(&executor)
.start()
.via(&executor)
.getVia(&executor));
}
#endif #endif
...@@ -2024,22 +2024,23 @@ class FutureAwaitable { ...@@ -2024,22 +2024,23 @@ class FutureAwaitable {
: future_(std::move(future)) {} : future_(std::move(future)) {}
bool await_ready() const { bool await_ready() const {
return future_.isReady(); return false;
} }
T await_resume() { T await_resume() {
return std::move(future_).value(); return std::move(result_).value();
} }
void await_suspend(std::experimental::coroutine_handle<> h) { void await_suspend(std::experimental::coroutine_handle<> h) {
future_.setCallback_([h](Try<T>&&) mutable { future_.setCallback_([this, h](Try<T>&& result) mutable {
// Don't std::move() so the try is left in the future for await_resume() result_ = std::move(result);
h.resume(); h.resume();
}); });
} }
private: private:
folly::Future<T> future_; folly::Future<T> future_;
folly::Try<T> result_;
}; };
} // namespace detail } // namespace detail
......
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