mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
The addon calls into JS with node::MakeCallback from a libuv timer, so every call opens a top-level callback scope, like an I/O callback does. Signed-off-by: Nigro Simone <nigro.simone@gmail.com> PR-URL: https://github.com/nodejs/node/pull/66316 Refs: https://github.com/nodejs/performance/issues/24 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: James M Snell <jasnell@gmail.com>
59 lines
1.8 KiB
C++
59 lines
1.8 KiB
C++
#include <node.h>
|
|
#include <uv.h>
|
|
#include <v8.h>
|
|
|
|
using v8::Context;
|
|
using v8::Function;
|
|
using v8::FunctionCallbackInfo;
|
|
using v8::Global;
|
|
using v8::HandleScope;
|
|
using v8::Isolate;
|
|
using v8::Local;
|
|
using v8::Object;
|
|
using v8::Value;
|
|
|
|
struct State {
|
|
uv_timer_t timer;
|
|
Isolate* isolate;
|
|
int64_t n;
|
|
Global<Function> fn;
|
|
Global<Function> done;
|
|
};
|
|
|
|
static void OnTimer(uv_timer_t* handle) {
|
|
State* state = static_cast<State*>(handle->data);
|
|
Isolate* isolate = state->isolate;
|
|
HandleScope handle_scope(isolate);
|
|
Local<Function> fn = state->fn.Get(isolate);
|
|
Local<Context> context = fn->GetCreationContextChecked(isolate);
|
|
Context::Scope context_scope(context);
|
|
Local<Object> recv = context->Global();
|
|
for (int64_t i = 0; i < state->n; i++) {
|
|
HandleScope inner_scope(isolate);
|
|
(void)node::MakeCallback(isolate, recv, fn, 0, nullptr, {0, 0});
|
|
}
|
|
Local<Function> done = state->done.Get(isolate);
|
|
(void)node::MakeCallback(isolate, recv, done, 0, nullptr, {0, 0});
|
|
uv_close(reinterpret_cast<uv_handle_t*>(&state->timer),
|
|
[](uv_handle_t* h) { delete static_cast<State*>(h->data); });
|
|
}
|
|
|
|
// run(n, fn, done): calls fn n times from a timer, then calls done.
|
|
static void Run(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
State* state = new State;
|
|
state->isolate = isolate;
|
|
state->n = args[0]->IntegerValue(isolate->GetCurrentContext()).FromJust();
|
|
state->fn.Reset(isolate, args[1].As<Function>());
|
|
state->done.Reset(isolate, args[2].As<Function>());
|
|
state->timer.data = state;
|
|
uv_timer_init(node::GetCurrentEventLoop(isolate), &state->timer);
|
|
uv_timer_start(&state->timer, OnTimer, 0, 0);
|
|
}
|
|
|
|
static void Initialize(Local<Object> target, Local<Value> module, void* data) {
|
|
NODE_SET_METHOD(target, "run", Run);
|
|
}
|
|
|
|
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
|