我有一个多线程C ++插件,可以进行一些后台处理,我需要定期回调我在NodeJS服务器上编写的Javascript函数。
我知道这涉及到使用uv_async_send(),因为它需要在主线程中执行,但到目前为止我还没有能够弄清楚如何去做。
那里有一个我错过的简单例子吗?
答案 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_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_init
和uv_close
。
如果您的uv_async_t
实例是动态分配的,请注意,在uv_close进行回调之前,您可能无法释放内存,以便让您知道这样做是安全的。
即:
auto async = new uv_async_t();
...
uv_close((uv_handle_t*)async, [](uv_handle_t* handle) {
delete handle;
});