mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-20 17:31:30 +00:00
106 lines
2.1 KiB
C++
106 lines
2.1 KiB
C++
#pragma once
|
|
#include <functional>
|
|
#include <exception>
|
|
#include "event_loop.h"
|
|
#include "../any.h"
|
|
|
|
namespace EQ {
|
|
class Task
|
|
{
|
|
public:
|
|
typedef std::function<void(const EQEmu::Any&)> ResolveFn;
|
|
typedef std::function<void(const std::exception&)> RejectFn;
|
|
typedef std::function<void()> FinallyFn;
|
|
typedef std::function<void(ResolveFn, RejectFn)> 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;
|
|
};
|
|
}
|