从multithreadingC ++插件callbackNodeJS Javascript函数
我有一个multithreading的C ++插件,做了一些后台处理,我需要定期callback一下我在NodeJS服务器上写的Javascript函数。
我明白,这涉及到使用uv_async_send(),因为它需要在主线程中执行,但到目前为止,我还没有能够弄清楚如何做到这一点。
有一个简单的例子,我错过了吗?
最后,一旦我了解了uv_ *函数的作用,这并不难:
1)在插件中公开一个函数,允许Node设置将被定期callback的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() // Ie 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
,传递上面的asynchronous实例,只要我们需要定期callback
uv_async_send(&async);
4)最后,当我们不再需要再次执行callback时,清理一下:
uv_close((uv_handle_t*) &async, NULL);
附录:
自从我写了这个答案后,我遇到了其他的问题,最后学到了关于libuv的一些教训。 为了完整,你应该明白:
-
除了
uv_async_send
之外, 所有 libuv函数只能从主循环线程调用! (我曾经看到它提到其他的不是线程安全的,但是这个语句太弱了)。例如,甚至,uv_async_init
和uv_close
必须从主循环线程调用。 -
如果您的
uv_async_t
实例是dynamic分配的,请注意,您可能无法释放内存,直到uv_close进行callback,让您知道这样做是安全的。
即:
auto async = new uv_async_t(); ... uv_close((uv_handle_t*)async, [](uv_handle_t* handle) { delete handle; });