task.h

#ifndef ASYNCIO_TASK_H
#define ASYNCIO_TASK_H
#include <asyncio/handle.h>
#include <asyncio/event_loop.h>
#include <asyncio/result.h>
#include <asyncio/concept/promise.h>
#include <coroutine>
#include <cassert>
#include <variant>
#include <memory>

namespace ASYNCIO_NS {
struct NoWaitAtInitialSuspend {};
inline constexpr NoWaitAtInitialSuspend no_wait_at_initial_suspend;

template<typename R = void> // R为Task的返回类型
struct Task: private NonCopyable {  // Task作为协程函数的返回值(Task必须有一个promise_type,必须重载co_await)
    struct promise_type;
    using coro_handle = std::coroutine_handle<promise_type>;

    template<concepts::Future>
    friend struct ScheduledTask;

    explicit Task(coro_handle h) noexcept: handle_(h) {}

    Task(Task&& t) noexcept
        : handle_(std::exchange(t.handle_, {})) {}

    ~Task() { destroy(); }

    // 获取Task返回值
    decltype(auto) get_result() & {
        return handle_.promise().result();
    }

    decltype(auto) get_result() && {
        return std::move(handle_.promise()).result();
    }

    // co_await返回值的基类
    struct AwaiterBase {
        constexpr bool await_ready() {
            if (self_coro_) [[likely]]  // 有句柄,就检查句柄是否执行完成
            { return self_coro_.done(); }   
            return true;
        }

        template<typename Promise>
        void await_suspend(std::coroutine_handle<Promise> resumer) const noexcept {
            assert(! self_coro_.promise().continuation_);
            // 将调用co_await Task的协程状态设置为SUSPEND,因为需要等待Task执行返回
            resumer.promise().set_state(Handle::SUSPEND);
            // 当前任务执行完或者挂起,就会执行continuation_,将continuation_指定为为调用Task的协程的句柄
            self_coro_.promise().continuation_ = &resumer.promise();    
            self_coro_.promise().schedule();    // 将当前协程加入句柄
        }

        coro_handle self_coro_ {};  // Task所属协程的句柄
    };

    // 重载co_await运算符(左值引用调用)
    auto operator co_await() const & noexcept {
        struct Awaiter: AwaiterBase {
            decltype(auto) await_resume() const {
                if (! AwaiterBase::self_coro_) [[unlikely]]
                { throw InvalidFuture{}; }
                return AwaiterBase::self_coro_.promise().result();  // 返回结果
            }
        };
        return Awaiter {handle_};   // Awaiter的协程句柄就是Task所属协程的句柄
    }

    // 重载co_await运算符(右值引用调用)
    auto operator co_await() const && noexcept {
        struct Awaiter: AwaiterBase {
            decltype(auto) await_resume() const {
                if (! AwaiterBase::self_coro_) [[unlikely]]
                { throw InvalidFuture{}; }
                return std::move(AwaiterBase::self_coro_.promise()).result();   // 返回结果
            }
        };
        return Awaiter {handle_};   // Awaiter的协程句柄就是Task所属协程的句柄
    }

    struct promise_type: CoroHandle, Result<R> {    // promise_type既是协程句柄,也是结果
        promise_type() = default;

        // 
        template<typename... Args> // from free function
        promise_type(NoWaitAtInitialSuspend, Args&&...): wait_at_initial_suspend_{false} { }

        // 
        template<typename Obj, typename... Args> // from member function
        promise_type(Obj&&, NoWaitAtInitialSuspend, Args&&...): wait_at_initial_suspend_{false} { }

        // 
        auto initial_suspend() noexcept {
            struct InitialSuspendAwaiter {
                constexpr bool await_ready() const noexcept { return !wait_at_initial_suspend_; }   // 协程初始需要挂起
                constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
                constexpr void await_resume() const noexcept {}
                const bool wait_at_initial_suspend_{true};
            };
            return InitialSuspendAwaiter{wait_at_initial_suspend_};
        }

        struct FinalAwaiter {
            constexpr bool await_ready() const noexcept { return false; }   // 协程结束需要挂起
            
            template<typename Promise>
            constexpr void await_suspend(std::coroutine_handle<Promise> h) const noexcept { 
                if (auto cont = h.promise().continuation_) {    // 将调用co_await Task的协程的句柄加入调度
                    get_event_loop().call_soon(*cont);
                }
            }

            constexpr void await_resume() const noexcept {}
        };

        auto final_suspend() noexcept {
            return FinalAwaiter {};
        }

        Task get_return_object() noexcept {
            return Task{coro_handle::from_promise(*this)};
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // 这些是CoroHandle的函数实现
        void run() final {  // run就是调用当前协程句柄
            coro_handle::from_promise(*this).resume();
        }
        
        const std::source_location& get_frame_info() const final { return frame_info_; }
        
        void dump_backtrace(size_t depth = 0) const final {
            fmt::print("[{}] {}\n", depth, frame_name());
            if (continuation_) { continuation_->dump_backtrace(depth + 1);  // 调用上一次的函数 }
            else { fmt::print("\n"); }
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////

        const bool wait_at_initial_suspend_ {true}; // 是否在协程开始时挂起
        CoroHandle* continuation_ {};               // 记录调用Task的协程的句柄
        std::source_location frame_info_{};         // 代码所在位置
    };

    bool valid() const { return handle_ != nullptr; }   // 任务是否合法:句柄是否存在

    bool done() const { return handle_.done(); }    // 任务是否完成:句柄是否执行完成

private:
    void destroy() {
        if (auto handle = std::exchange(handle_, nullptr)) {
            handle.promise().cancel();
            handle.destroy();
        }
    }

private:
    coro_handle handle_;    // 协程句柄
};

static_assert(concepts::Promise<Task<>::promise_type>);
static_assert(concepts::Future<Task<>>);
}
#endif // ASYNCIO_TASK_H

posted @ 2024-07-12 17:02  DavidJIAN  阅读(5)  评论(0)    收藏  举报