diff options
author | snaury <snaury@ydb.tech> | 2023-08-08 17:18:33 +0300 |
---|---|---|
committer | snaury <snaury@ydb.tech> | 2023-08-08 18:14:19 +0300 |
commit | e8f301ee51eb89ff10308d312557586ac0261c3d (patch) | |
tree | 5f8b923d708622d228d1f6e6387cd715154c6f03 /library/cpp/actors/cppcoro/task_result.h | |
parent | f95fc3633ff92fc77fbc6220aa9b3653d0df412e (diff) | |
download | ydb-e8f301ee51eb89ff10308d312557586ac0261c3d.tar.gz |
Better C++ coroutine lifetime in actors KIKIMR-18962
Diffstat (limited to 'library/cpp/actors/cppcoro/task_result.h')
-rw-r--r-- | library/cpp/actors/cppcoro/task_result.h | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/library/cpp/actors/cppcoro/task_result.h b/library/cpp/actors/cppcoro/task_result.h new file mode 100644 index 0000000000..70176e64d5 --- /dev/null +++ b/library/cpp/actors/cppcoro/task_result.h @@ -0,0 +1,113 @@ +#pragma once +#include <util/system/yassert.h> +#include <exception> +#include <variant> + +namespace NActors { + + namespace NDetail { + + struct TVoid {}; + + template<class T> + struct TReplaceVoid { + using TType = T; + }; + + template<> + struct TReplaceVoid<void> { + using TType = TVoid; + }; + + template<class T> + struct TLValue { + using TType = T&; + }; + + template<> + struct TLValue<void> { + using TType = void; + }; + + template<class T> + struct TRValue { + using TType = T&&; + }; + + template<> + struct TRValue<void> { + using TType = void; + }; + + } // namespace NDetail + + /** + * Wrapper for the task result + */ + template<class T> + class TTaskResult { + public: + void SetValue() + requires (std::same_as<T, void>) + { + Result.template emplace<1>(); + } + + template<class TResult> + void SetValue(TResult&& result) + requires (!std::same_as<T, void>) + { + Result.template emplace<1>(std::forward<TResult>(result)); + } + + void SetException(std::exception_ptr&& e) noexcept { + Result.template emplace<2>(std::move(e)); + } + + typename NDetail::TLValue<T>::TType Value() & { + switch (Result.index()) { + case 0: { + Y_FAIL("Task result has no value"); + } + case 1: { + if constexpr (std::same_as<T, void>) { + return; + } else { + return std::get<1>(Result); + } + } + case 2: { + std::exception_ptr& e = std::get<2>(Result); + Y_VERIFY_DEBUG(e, "Task exception missing"); + std::rethrow_exception(e); + } + } + Y_FAIL("Task result has an invalid state"); + } + + typename NDetail::TRValue<T>::TType Value() && { + switch (Result.index()) { + case 0: { + Y_FAIL("Task result has no value"); + } + case 1: { + if constexpr (std::same_as<T, void>) { + return; + } else { + return std::get<1>(std::move(Result)); + } + } + case 2: { + std::exception_ptr& e = std::get<2>(Result); + Y_VERIFY_DEBUG(e, "Task exception missing"); + std::rethrow_exception(std::move(e)); + } + } + Y_FAIL("Task result has an invalid state"); + } + + private: + std::variant<std::monostate, typename NDetail::TReplaceVoid<T>::TType, std::exception_ptr> Result; + }; + +} // namespace NActors |