#pragma once #include "Awaiter.h" namespace clice::async { namespace awaiter { template struct value { std::optional value; }; template <> struct value {}; template struct thread_pool : value, uv, uv_work_t, Ret, int> { Work work; /// `uv_work_t` has two callback functions, `work_cb` is executed in the thread pool, /// and `after_work_cb` is executed in the main thread. static void work_cb(uv_work_t* work) { auto& awaiter = uv_cast(work); if constexpr(!std::is_void_v) { awaiter.value.emplace(awaiter.work()); } else { awaiter.work(); } } int start(auto callback) { return uv_queue_work(async::loop, &this->request, work_cb, callback); } void cleanup(int status) { this->error = status; } Ret result() { if constexpr(!std::is_void_v) { return std::move(*this->value); } } }; } // namespace awaiter template > async::Task submit(Work&& work) { using W = std::remove_cvref_t; auto result = co_await awaiter::thread_pool{{}, {}, std::forward(work)}; if(!result) { /// Thread pool task should never fails. std::abort(); } co_return std::move(*result); } } // namespace clice::async