Added a new Nan tool
This commit is contained in:
parent
e82ae7cab1
commit
4c264a7225
101
native/dist/ext_nan/include/NanEventCallback.h
vendored
101
native/dist/ext_nan/include/NanEventCallback.h
vendored
@ -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;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user