Commit dde95013 authored by Shai Szulanski's avatar Shai Szulanski Committed by Facebook GitHub Bot

Add yield_value(Try<>) to coro::Task

Summary: Generic code taking in a `Task<void|T>` cannot easily forward the result without throwing exceptions because the `return_value` overload taking a `Try` cannot be added to `Task<void>` which already has `return_void`. Instead we use `yield_value` as we did with `co_error` to make the desired generic code possible.

Reviewed By: lewissbaker

Differential Revision: D22934887

fbshipit-source-id: ec50de5832f9038d92749bdde2c1d43244288a3c
parent 5076d050
...@@ -51,6 +51,25 @@ class Task; ...@@ -51,6 +51,25 @@ class Task;
template <typename T = void> template <typename T = void>
class TaskWithExecutor; class TaskWithExecutor;
template <typename T>
class co_result final {
public:
explicit co_result(Try<T>&& result) noexcept(
std::is_nothrow_move_constructible<T>::value)
: result_(std::move(result)) {}
const Try<T>& result() const {
return result_;
}
Try<T>& result() {
return result_;
}
private:
Try<T> result_;
};
namespace detail { namespace detail {
class TaskPromiseBase { class TaskPromiseBase {
...@@ -175,6 +194,11 @@ class TaskPromise : public TaskPromiseBase { ...@@ -175,6 +194,11 @@ class TaskPromise : public TaskPromiseBase {
return final_suspend(); return final_suspend();
} }
auto yield_value(co_result<StorageType>&& result) {
result_ = std::move(result.result());
return final_suspend();
}
private: private:
Try<StorageType> result_; Try<StorageType> result_;
}; };
...@@ -206,6 +230,11 @@ class TaskPromise<void> : public TaskPromiseBase { ...@@ -206,6 +230,11 @@ class TaskPromise<void> : public TaskPromiseBase {
return final_suspend(); return final_suspend();
} }
auto yield_value(co_result<void>&& result) {
result_ = std::move(result.result());
return final_suspend();
}
private: private:
Try<void> result_; Try<void> result_;
}; };
......
...@@ -449,4 +449,39 @@ TEST_F(TaskTest, StartInlineUnsafe) { ...@@ -449,4 +449,39 @@ TEST_F(TaskTest, StartInlineUnsafe) {
}()); }());
} }
TEST_F(TaskTest, YieldTry) {
folly::coro::blockingWait([]() -> folly::coro::Task<void> {
auto innerTaskVoid = []() -> folly::coro::Task<void> {
co_yield folly::coro::co_error(std::runtime_error(""));
}();
auto retVoid = co_await co_awaitTry([&]() -> folly::coro::Task<void> {
co_yield folly::coro::co_result(
co_await co_awaitTry(std::move(innerTaskVoid)));
}());
EXPECT_TRUE(retVoid.hasException());
innerTaskVoid = []() -> folly::coro::Task<void> { co_return; }();
retVoid = co_await co_awaitTry([&]() -> folly::coro::Task<void> {
co_yield folly::coro::co_result(
co_await co_awaitTry(std::move(innerTaskVoid)));
}());
EXPECT_FALSE(retVoid.hasException());
auto innerTaskInt = []() -> folly::coro::Task<int> {
co_yield folly::coro::co_error(std::runtime_error(""));
}();
auto retInt = co_await co_awaitTry([&]() -> folly::coro::Task<int> {
co_yield folly::coro::co_result(
co_await co_awaitTry(std::move(innerTaskInt)));
}());
EXPECT_TRUE(retInt.hasException());
innerTaskInt = []() -> folly::coro::Task<int> { co_return 0; }();
retInt = co_await co_awaitTry([&]() -> folly::coro::Task<int> {
co_yield folly::coro::co_result(
co_await co_awaitTry(std::move(innerTaskInt)));
}());
EXPECT_TRUE(retInt.hasValue());
}());
}
#endif #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