来自多线程 C++ 插件的回调 NodeJS Javascript 函数

Callback NodeJS Javascript function from multithreaded C++ addon

我有一个多线程 C++ 插件,它执行一些后台处理,我需要让它定期回调到我在 NodeJS 服务器中编写的 Javascript 函数。

我知道这涉及使用 uv_async_send(),因为它需要在主线程中执行,但到目前为止我还没有弄清楚如何去做。

有没有我错过的简单示例?

最后,一旦我理解了 uv_* 函数的作用,这就不是太难了:

1) 在插件中公开一个函数以允许 Node 设置 Javascript cb 将定期回调到:

Callback* cbPeriodic; // keep cbPeriodic somewhere
NAN_METHOD(setPeriodicCb) {
    cbPeriodic = new Callback(info[0].As<Function>());
    //...
}

2) 使用一个uv_async_t实例和一个函数初始化UV,当我们的工作线程调用uv_async_send()时,UV将在主线程中执行该函数

uv_async_t async; // keep this instance around for as long as we might need to do the periodic callback
uv_loop_t* loop = uv_default_loop();
uv_async_init(loop, &async, asyncmsg);

void asyncmsg(uv_async_t* handle) {
  // Called by UV in main thread after our worker thread calls uv_async_send()
  //    I.e. it's safe to callback to the CB we defined in node!
  Nan::HandleScope scope;
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  Local<Value> argv[] = { v8::String::NewFromUtf8(isolate, "Hello world") };
  cbPeriodic->Call(1, argv);
}

3) 从工作线程调用 uv_async_send,传递上面的异步实例,每当我们需要执行周期性回调时

uv_async_send(&async);

4) 最后,当我们不再需要再次执行回调时,清理一下:

uv_close((uv_handle_t*) &async, NULL);

附录:

自从我写了这个答案后,我 运行 研究了其他问题,并最终学到了一些关于 libuv 的课程。为了完整起见,您应该了解:

  • 除了uv_async_send所有 libuv函数可能 从主循环线程调用! (我曾看到它提到其他人不是线程安全的,但这种说法太弱了。)甚至,例如,uv_async_inituv_close 也必须从主循环线程调用。

  • 如果您的 uv_async_t 实例是动态分配的,请注意您可能不会释放内存,直到 uv_close 发出回调通知您这样做是安全的.

即:

auto async = new uv_async_t();
...
uv_close((uv_handle_t*)async, [](uv_handle_t* handle) {
    delete handle;
});