#pragma once #include #include "pool.hpp" #include "io/uv/uvloop.hpp" #include "utils/placeholder.hpp" class Task { template using work_t = std::function; template using after_work_t = std::function; template struct Work { Work(work_t work, after_work_t after_work) : work(std::move(work)), after_work(std::move(after_work)) { req.data = static_cast(this); } void operator()() { result.set(std::move(work())); } work_t work; after_work_t after_work; Placeholder result; uv_work_t req; static void work_cb(uv_work_t* req) { auto& work = *static_cast*>(req->data); work(); } static void after_work_cb(uv_work_t* req, int) { auto work = static_cast*>(req->data); work->after_work(std::move(work->result.get())); delete work; } }; public: using sptr = std::shared_ptr; Task(uv::UvLoop::sptr loop) : loop(loop) {} Task(Task&) = delete; Task(Task&&) = delete; template void run(F1&& work, F2&& after_work) { using T = decltype(work()); auto w = new Work(std::forward(work), std::forward(after_work)); uv_queue_work(*loop, &w->req, Work::work_cb, Work::after_work_cb); } private: uv::UvLoop::sptr loop; };