Added a new Nan tool
This commit is contained in:
parent
e82ae7cab1
commit
4c264a7225
|
@ -208,4 +208,105 @@ namespace Nan {
|
||||||
auto handle = std::make_shared<lambda>(std::forward<lambda>(lam));
|
auto handle = std::make_shared<lambda>(std::forward<lambda>(lam));
|
||||||
return async_callback(lambda_info::wrap(handle));
|
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;
|
||||||
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue