从多线程C ++插件回调NodeJS Javascript函数

时间:2016-05-02 16:35:10

标签: javascript c++ node.js multithreading v8

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

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

那里有一个我错过的简单例子吗?

1 个答案:

答案 0 :(得分:17)

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

1)在插件中公开一个函数,允许Node设置定期调用的Javascript cb:

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

2)初始UV带有uv_async_t实例,当我们的工作线程调用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;
});