diff --git a/modules/async_context.cppm b/modules/async_context.cppm index f99dcf8..ffcafc3 100644 --- a/modules/async_context.cppm +++ b/modules/async_context.cppm @@ -902,7 +902,9 @@ public: .promise() .get_context() .resume(); - } else if (std::holds_alternative(m_state)) { + } + + if (std::holds_alternative(m_state)) { std::rethrow_exception(std::get(m_state)); } } @@ -947,7 +949,8 @@ public: { future& m_operation; - constexpr explicit awaiter(future& p_operation) noexcept + constexpr explicit awaiter(future& p_operation + [[clang::lifetimebound]]) noexcept : m_operation(p_operation) { } @@ -975,26 +978,29 @@ public: constexpr monostate_or& await_resume() const requires(not std::is_void_v) { - // Combined with await_ready's `>= 1`, this becomes `== 1` - if (m_operation.m_state.index() < 2) [[likely]] { - return *std::get_if<1>(&m_operation.m_state); - } - // index >= 2, error territory - if (m_operation.m_state.index() == 3) { - std::rethrow_exception(*std::get_if<3>(&m_operation.m_state)); + if (std::holds_alternative(m_operation.m_state)) [[likely]] { + return std::get(m_operation.m_state); + } else if (std::holds_alternative( + m_operation.m_state)) [[unlikely]] { + std::rethrow_exception( + std::get(m_operation.m_state)); } + throw operation_cancelled{}; } constexpr void await_resume() const requires(std::is_void_v) { - if (m_operation.m_state.index() < 2) [[likely]] { + if (std::holds_alternative(m_operation.m_state)) + [[likely]] { return; + } else if (std::holds_alternative( + m_operation.m_state)) [[unlikely]] { + std::rethrow_exception( + std::get(m_operation.m_state)); } - if (m_operation.m_state.index() == 3) { - std::rethrow_exception(*std::get_if<3>(&m_operation.m_state)); - } + throw operation_cancelled{}; } }; @@ -1079,6 +1085,13 @@ private: future_state m_state{}; }; +/** + * @brief An async task is an async operation that performs some work but + * doesn't return a value. + * + */ +export using task = future; + template constexpr future promise::get_return_object() noexcept { @@ -1088,7 +1101,7 @@ constexpr future promise::get_return_object() noexcept return future{ handle }; } -inline constexpr future promise::get_return_object() noexcept +constexpr future promise::get_return_object() noexcept { using future_handle = std::coroutine_handle>; auto handle = future_handle::from_promise(*this); diff --git a/tests/cancel.test.cpp b/tests/cancel.test.cpp index a4bc241..2395fe4 100644 --- a/tests/cancel.test.cpp +++ b/tests/cancel.test.cpp @@ -205,7 +205,6 @@ boost::ut::suite<"cancellation_tests"> cancellation_tests = []() { expect(throws([&]() { future.resume(); - future.resume(); })) << "runtime_error exception was not thrown!"; expect(that % future.done());