aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/actors/cppcoro/task_result.h
diff options
context:
space:
mode:
authorsnaury <snaury@ydb.tech>2023-08-08 17:18:33 +0300
committersnaury <snaury@ydb.tech>2023-08-08 18:14:19 +0300
commite8f301ee51eb89ff10308d312557586ac0261c3d (patch)
tree5f8b923d708622d228d1f6e6387cd715154c6f03 /library/cpp/actors/cppcoro/task_result.h
parentf95fc3633ff92fc77fbc6220aa9b3653d0df412e (diff)
downloadydb-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.h113
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