#pragma once #include #include #include "event_loop.h" #include "../any.h" namespace EQ { class Task { public: typedef std::function ResolveFn; typedef std::function RejectFn; typedef std::function FinallyFn; typedef std::function TaskFn; struct TaskBaton { TaskFn fn; ResolveFn on_then; RejectFn on_catch; FinallyFn on_finally; bool has_result; EQEmu::Any result; bool has_error; std::exception error; }; Task(EventLoop &loop, TaskFn fn) : _loop(loop) { _fn = fn; } Task(TaskFn fn) : _loop(EventLoop::GetDefault()) { _fn = fn; } ~Task() { } Task& Then(ResolveFn fn) { _then = fn; return *this; } Task& Catch(RejectFn fn) { _catch = fn; return *this; } Task& Finally(FinallyFn fn) { _fin = fn; return *this; } void Run() { uv_work_t *work = new uv_work_t; memset(work, 0, sizeof(uv_work_t)); TaskBaton *baton = new TaskBaton(); baton->fn = _fn; baton->on_then = _then; baton->on_catch = _catch; baton->on_finally = _fin; baton->has_result = false; baton->has_error = false; work->data = baton; uv_queue_work(_loop.Handle(), work, [](uv_work_t* req) { TaskBaton *baton = (TaskBaton*)req->data; baton->fn([baton](const EQEmu::Any& result) { baton->has_error = false; baton->has_result = true; baton->result = result; }, [baton](const std::exception &err) { baton->has_error = true; baton->has_result = false; baton->error = err; }); }, [](uv_work_t* req, int status) { TaskBaton *baton = (TaskBaton*)req->data; if (baton->has_error && baton->on_catch) { baton->on_catch(baton->error); } else if (baton->has_result && baton->on_then) { baton->on_then(baton->result); } if (baton->on_finally) { baton->on_finally(); } delete baton; delete req; }); } private: TaskFn _fn; ResolveFn _then; RejectFn _catch; FinallyFn _fin; EventLoop &_loop; }; }