task_result.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #pragma once
  2. #include <util/system/yassert.h>
  3. #include <exception>
  4. #include <variant>
  5. namespace NActors {
  6. namespace NDetail {
  7. struct TVoid {};
  8. template<class T>
  9. struct TReplaceVoid {
  10. using TType = T;
  11. };
  12. template<>
  13. struct TReplaceVoid<void> {
  14. using TType = TVoid;
  15. };
  16. template<class T>
  17. struct TLValue {
  18. using TType = T&;
  19. };
  20. template<>
  21. struct TLValue<void> {
  22. using TType = void;
  23. };
  24. template<class T>
  25. struct TRValue {
  26. using TType = T&&;
  27. };
  28. template<>
  29. struct TRValue<void> {
  30. using TType = void;
  31. };
  32. } // namespace NDetail
  33. /**
  34. * Wrapper for the task result
  35. */
  36. template<class T>
  37. class TTaskResult {
  38. public:
  39. void SetValue()
  40. requires (std::same_as<T, void>)
  41. {
  42. Result.template emplace<1>();
  43. }
  44. template<class TResult>
  45. void SetValue(TResult&& result)
  46. requires (!std::same_as<T, void>)
  47. {
  48. Result.template emplace<1>(std::forward<TResult>(result));
  49. }
  50. void SetException(std::exception_ptr&& e) noexcept {
  51. Result.template emplace<2>(std::move(e));
  52. }
  53. typename NDetail::TLValue<T>::TType Value() & {
  54. switch (Result.index()) {
  55. case 0: {
  56. Y_ABORT("Task result has no value");
  57. }
  58. case 1: {
  59. if constexpr (std::same_as<T, void>) {
  60. return;
  61. } else {
  62. return std::get<1>(Result);
  63. }
  64. }
  65. case 2: {
  66. std::exception_ptr& e = std::get<2>(Result);
  67. Y_DEBUG_ABORT_UNLESS(e, "Task exception missing");
  68. std::rethrow_exception(e);
  69. }
  70. }
  71. Y_ABORT("Task result has an invalid state");
  72. }
  73. typename NDetail::TRValue<T>::TType Value() && {
  74. switch (Result.index()) {
  75. case 0: {
  76. Y_ABORT("Task result has no value");
  77. }
  78. case 1: {
  79. if constexpr (std::same_as<T, void>) {
  80. return;
  81. } else {
  82. return std::get<1>(std::move(Result));
  83. }
  84. }
  85. case 2: {
  86. std::exception_ptr& e = std::get<2>(Result);
  87. Y_DEBUG_ABORT_UNLESS(e, "Task exception missing");
  88. std::rethrow_exception(std::move(e));
  89. }
  90. }
  91. Y_ABORT("Task result has an invalid state");
  92. }
  93. private:
  94. std::variant<std::monostate, typename NDetail::TReplaceVoid<T>::TType, std::exception_ptr> Result;
  95. };
  96. } // namespace NActors