#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(uv::UvLoop& loop, work_t work, after_work_t after_work) : work(std::move(work)), after_work(std::move(after_work)) { uv_async_init(loop, &this->async, async_cb); } void operator()() { result.set(std::move(work())); async.data = static_cast(this); uv_async_send(&this->async); } work_t work; after_work_t after_work; Placeholder result; uv_async_t async; private: static void async_cb(uv_async_t* handle) { auto work = static_cast*>(handle->data); work->after_work(std::move(work->result.get())); auto async_as_handle = reinterpret_cast(handle); uv_close(async_as_handle, [](uv_handle_t* handle) { auto work = static_cast*>(handle->data); delete work; }); } }; public: using sptr = std::shared_ptr; Task(uv::UvLoop::sptr loop, Pool::sptr pool) : loop(loop), pool(pool) {} Task(Task&) = delete; Task(Task&&) = delete; template void run(F1&& work, F2&& after_work) { using T = decltype(work()); auto w = new Work(*loop, std::forward(work), std::forward(after_work)); pool->run([w]() { w->operator()(); }); } private: uv::UvLoop::sptr loop; Pool::sptr pool; };