export module mcpplibs.cmp:task; import std; export namespace mcpplibs::cmp { // 完成时对称转移到等待方,避免嵌套 Task 持续增长原生调用栈 template requires ( std::same_as || (std::is_object_v && !std::is_array_v) ) class [[nodiscard]] Task { public: struct promise_type { std::optional result_ {}; std::exception_ptr exception_ {}; std::coroutine_handle<> continuation_ { std::noop_coroutine() }; [[nodiscard]] Task get_return_object() noexcept; [[nodiscard]] constexpr std::suspend_always initial_suspend() const noexcept { return {}; } class FinalAwaiter { public: [[nodiscard]] constexpr bool await_ready() const noexcept { return false; } [[nodiscard]] std::coroutine_handle<> await_suspend( std::coroutine_handle coroutine) const noexcept { return coroutine.promise().continuation_; } constexpr void await_resume() const noexcept {} }; [[nodiscard]] constexpr FinalAwaiter final_suspend() const noexcept { return {}; } template requires std::constructible_from void return_value(U&& value) noexcept(std::is_nothrow_constructible_v) { result_.emplace(std::forward(value)); } void unhandled_exception() noexcept { exception_ = std::current_exception(); } }; private: using Handle = std::coroutine_handle; class Awaiter { private: Handle coroutine_ {}; public: explicit Awaiter(Handle coroutine) noexcept : coroutine_ { coroutine } {} Awaiter(const Awaiter&) = delete; Awaiter& operator=(const Awaiter&) = delete; Awaiter(Awaiter&& other) noexcept : coroutine_ { std::exchange(other.coroutine_, {}) } {} Awaiter& operator=(Awaiter&&) = delete; ~Awaiter() { if (coroutine_) { coroutine_.destroy(); } } [[nodiscard]] constexpr bool await_ready() const noexcept { return false; } [[nodiscard]] std::coroutine_handle<> await_suspend( std::coroutine_handle<> continuation) noexcept { coroutine_.promise().continuation_ = continuation; return coroutine_; } T await_resume() { auto& promise = coroutine_.promise(); if (promise.exception_) { std::rethrow_exception(promise.exception_); } return std::move(*promise.result_); } }; Handle coroutine_ {}; explicit Task(Handle coroutine) noexcept : coroutine_ { coroutine } {} public: Task() = delete; Task(const Task&) = delete; Task& operator=(const Task&) = delete; Task(Task&& other) noexcept : coroutine_ { std::exchange(other.coroutine_, {}) } {} Task& operator=(Task&&) = delete; ~Task() { if (coroutine_) { coroutine_.destroy(); } } [[nodiscard]] auto operator co_await() && noexcept { if (!coroutine_) { std::terminate(); } return Awaiter { std::exchange(coroutine_, {}) }; } }; template requires ( std::same_as || (std::is_object_v && !std::is_array_v) ) Task Task::promise_type::get_return_object() noexcept { return Task { std::coroutine_handle::from_promise(*this) }; } template<> class [[nodiscard]] Task { public: struct promise_type { std::exception_ptr exception_ {}; std::coroutine_handle<> continuation_ { std::noop_coroutine() }; [[nodiscard]] Task get_return_object() noexcept; [[nodiscard]] constexpr std::suspend_always initial_suspend() const noexcept { return {}; } class FinalAwaiter { public: [[nodiscard]] constexpr bool await_ready() const noexcept { return false; } [[nodiscard]] std::coroutine_handle<> await_suspend( std::coroutine_handle coroutine) const noexcept { return coroutine.promise().continuation_; } constexpr void await_resume() const noexcept {} }; [[nodiscard]] constexpr FinalAwaiter final_suspend() const noexcept { return {}; } constexpr void return_void() const noexcept {} void unhandled_exception() noexcept { exception_ = std::current_exception(); } }; private: using Handle = std::coroutine_handle; class Awaiter { private: Handle coroutine_ {}; public: explicit Awaiter(Handle coroutine) noexcept : coroutine_ { coroutine } {} Awaiter(const Awaiter&) = delete; Awaiter& operator=(const Awaiter&) = delete; Awaiter(Awaiter&& other) noexcept : coroutine_ { std::exchange(other.coroutine_, {}) } {} Awaiter& operator=(Awaiter&&) = delete; ~Awaiter() { if (coroutine_) { coroutine_.destroy(); } } [[nodiscard]] constexpr bool await_ready() const noexcept { return false; } [[nodiscard]] std::coroutine_handle<> await_suspend( std::coroutine_handle<> continuation) noexcept { coroutine_.promise().continuation_ = continuation; return coroutine_; } void await_resume() { auto& promise = coroutine_.promise(); if (promise.exception_) { std::rethrow_exception(promise.exception_); } } }; Handle coroutine_ {}; explicit Task(Handle coroutine) noexcept : coroutine_ { coroutine } {} public: Task() = delete; Task(const Task&) = delete; Task& operator=(const Task&) = delete; Task(Task&& other) noexcept : coroutine_ { std::exchange(other.coroutine_, {}) } {} Task& operator=(Task&&) = delete; ~Task() { if (coroutine_) { coroutine_.destroy(); } } [[nodiscard]] auto operator co_await() && noexcept { if (!coroutine_) { std::terminate(); } return Awaiter { std::exchange(coroutine_, {}) }; } }; inline Task Task::promise_type::get_return_object() noexcept { return Task { std::coroutine_handle::from_promise(*this) }; } } // namespace mcpplibs::cmp