#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 ()())> auto submit(Work&& work) { return awaiter::thread_pool, Ret>{{}, {}, std::forward(work)}; } } // namespace clice::async