#pragma once
#include "co_context/io_context.h"
#include "co_context/detail/io_context_meta.h"
namespace co_context {
    io_context::io_context() noexcept
    {
        auto& meta = detail::io_context_meta;
        std::lock_guard lg{meta.mtx};
        id = meta.create_count++;
    }
    void io_context::init()
    {
        detail::this_thread.ctx = this;
        detail::this_thread.ctx_id = id;
        worker.init();
    }
    void io_context::deinit()
    {
        detail::this_thread.ctx = nullptr;
        detail::this_thread.ctx_id = static_cast<ctx_id_t>(-1);

        worker.deinit();

        auto& meta = detail::io_context_meta;
        std::lock_guard lg{meta.mtx};
        --meta.ready_count;
        --meta.create_count;
    }
    void io_context::start()
    {
        init();
        run();
    }
    void io_context::co_spawn(task<void>&& entrance) noexcept {
        auto handle = entrance.get_handle();
        entrance.detach();
        worker.forward_task(handle);
    }
    void io_context::run()
    {
        while (!will_stop) [[likely]] {
            do_worker_part();

            do_submission_part();

            do_completion_part();
        }
    }
    void io_context::do_submission_part() noexcept
    {
        worker.poll_submission();
    }
    void io_context::do_completion_part() noexcept
    {
        const uint32_t handled_num = worker.poll_completion();

        bool is_not_over = handled_num | worker.requests_to_reap;

        if (!is_not_over) [[unlikely]] {
            will_stop = true;
        }
    }
    void io_context::do_worker_part()
    {
        auto num = worker.number_to_schedule();
        for (; num > 0; --num) {
            worker.work_once();
        }
    }
} // namespace co_context
