Added a new Nan tool

This commit is contained in:
WolverinDEV 2021-03-28 21:36:25 +02:00
parent e82ae7cab1
commit 4c264a7225

View File

@ -208,4 +208,105 @@ namespace Nan {
auto handle = std::make_shared<lambda>(std::forward<lambda>(lam));
return async_callback(lambda_info::wrap(handle));
}
struct JavaScriptQueue {
public:
explicit JavaScriptQueue() {
auto event_loop = Nan::GetCurrentEventLoop();
assert(event_loop);
this->callback_data = new CallbackData{};
uv_async_init(event_loop, &this->callback_data->handle, JavaScriptQueue::async_send_callback);
}
~JavaScriptQueue() {
{
std::lock_guard lock{this->callback_data->callback_mutex};
this->callback_data->destroy = true;
}
uv_async_send(&this->callback_data->handle);
}
JavaScriptQueue(const JavaScriptQueue&) = delete;
JavaScriptQueue(JavaScriptQueue&&) = delete;
template <typename lambda>
inline void enqueue(lambda&& callback) const {
auto callable = new Callable<lambda>(std::forward<lambda>(callback));
{
std::lock_guard lock{callback_data->callback_mutex};
*this->callback_data->callback_tail = callable;
this->callback_data->callback_tail = &callable->next;
}
uv_async_send(&this->callback_data->handle);
}
private:
struct AbstractCallable;
struct CallbackData {
uv_async_t handle;
bool destroy{false};
std::mutex callback_mutex{};
AbstractCallable* callback_head{nullptr};
AbstractCallable** callback_tail{&this->callback_head};
explicit CallbackData() {
memset(&this->handle, 0, sizeof(this->handle));
this->handle.data = this;
}
};
struct AbstractCallable {
AbstractCallable() = default;
virtual ~AbstractCallable() = default;
virtual void call() = 0;
AbstractCallable* next{nullptr};
};
template <typename lambda>
struct Callable : public AbstractCallable {
explicit Callable(lambda&& callback) : callback{std::forward<lambda>(callback)} {}
~Callable() override = default;
void call() override {
this->callback();
}
lambda callback;
};
static void async_send_callback(uv_async_t* handle) {
auto data = (CallbackData*) handle->data;
assert(data->handle.data == data);
std::unique_lock lock{data->callback_mutex};
auto destroy = data->destroy;
auto callback_head = std::exchange(data->callback_head, nullptr);
data->callback_tail = &data->callback_head;
lock.unlock();
Nan::HandleScope scope{};
while(callback_head) {
callback_head->call();
auto next = callback_head->next;
delete callback_head;
callback_head = next;
}
if(destroy) {
/* uv_async_t inherits from uv_handle_t */
uv_close((uv_handle_t*) handle, JavaScriptQueue::async_close_callback);
}
}
static void async_close_callback(uv_handle_t* handle) {
delete (CallbackData*) handle->data;
}
CallbackData* callback_data;
};
}