#include #include #include 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; // Same order as the types in index.js. enum Type { kMakeCallback, kAsyncResource, kCall }; struct State { uv_timer_t timer; Isolate* isolate; int64_t n; Type type; Global fn; Global done; node::AsyncResource* resource = nullptr; ~State() { delete resource; } }; static void OnTimer(uv_timer_t* handle) { State* state = static_cast(handle->data); Isolate* isolate = state->isolate; HandleScope handle_scope(isolate); Local fn = state->fn.Get(isolate); Local context = fn->GetCreationContextChecked(isolate); Context::Scope context_scope(context); Local recv = context->Global(); for (int64_t i = 0; i < state->n; i++) { HandleScope inner_scope(isolate); switch (state->type) { case kMakeCallback: (void)node::MakeCallback(isolate, recv, fn, 0, nullptr, {0, 0}); break; case kAsyncResource: (void)state->resource->MakeCallback(fn, 0, nullptr); break; case kCall: (void)fn->Call(context, recv, 0, nullptr); break; } } Local done = state->done.Get(isolate); (void)node::MakeCallback(isolate, recv, done, 0, nullptr, {0, 0}); uv_close(reinterpret_cast(&state->timer), [](uv_handle_t* h) { delete static_cast(h->data); }); } // run(n, fn, done, type): calls fn n times from a timer, then calls done. static void Run(const FunctionCallbackInfo& 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()); state->done.Reset(isolate, args[2].As()); state->type = static_cast( args[3]->Int32Value(isolate->GetCurrentContext()).FromJust()); if (state->type == kAsyncResource) { state->resource = new node::AsyncResource(isolate, Object::New(isolate), "Benchmark"); } state->timer.data = state; uv_timer_init(node::GetCurrentEventLoop(isolate), &state->timer); uv_timer_start(&state->timer, OnTimer, 0, 0); } static void Initialize(Local target, Local module, void* data) { NODE_SET_METHOD(target, "run", Run); } NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)