logidelic logidelic - 8 months ago 271
Javascript Question

Callback NodeJS Javascript function from multithreaded C++ addon

I have a multithreaded C++ addon that does some background processing and I need to have it periodically callback to a Javascript function that I wrote in my NodeJS server.

I understand that this involves using uv_async_send(), since it needs to get executed in the main thread, but thus far I haven't been able to figure out how to do it.

Is there a simple example out there that I've missed?


Finally, this was not too difficult once I understood what the the uv_* functions do:

1) Expose a function in the addon to allow Node to set the Javascript cb that will be periodically called back to:

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

2) Init UV with an uv_async_t instance and a function that will be executed in the main thread by UV when our worker thread calls 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) Call uv_async_send from a worker thread, passing our async instance above, whenever we need to do the periodic callback


4) Finally, when we no longer need to execute the callback ever again, clean things up:

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