Sepehr
Sepehr

Reputation: 2111

Calling a JS function by event emitting

I am not sure how one can call a Node/v8 function within Node's main thread by using event emitting in a separate C++ thread. How is it possible to emit events in a C++ thread?

Before thinking about NanAsyncWorker or uv_queue_work: I don't want to call a C++ function in an Async fashion. I want to do the exact opposite, calling a Javascript function from C++ by emitting events.

Upvotes: 6

Views: 1166

Answers (1)

loganfsmyth
loganfsmyth

Reputation: 161457

You do not need to use uv_queue_work, but part of LibUV's thread library are the uv_async_* methods, which are what you'd ideally have in this case. When you initialize your secondary thread, you'd also do uv_async_init to create a shared async data structure. This function is also called with a callback that will run whenever your other thread sends a message. That callback is where you would call the JS code to trigger your events.

Here's some semi psuedocode as an example:

In your thread init function called from JS with a single callback arg:

void ThreadInit(const v8::Arguments &args){
  // This is just an example, this should be saved somewhere that
  // some_callback will be able to access it.
  v8::Persistent<v8::Function> js_callback = args[0].As<Function>();

  // And save this where you'll be able to call uv_close on it.
  uv_async_t async_data;

  uv_async_init(uv_default_loop(), &async_data, some_callback);

  // initialize the thread and pass it async_data
}

In thread:

async_data.data = (void*) // Some data structure...
uv_async_send(&async_data);

In thread callback:

void some_callback(uv_async_t *async_data){
    // Note that this depending on the data, you could easily get thread-safety issues
    // here, so keep in mind that you should follow standard processes here.
    void* data = async_data->data;

    // Process that data however you need to in order to create a JS value, e.g.
    // Using NanNew because it is more readable than standard V8.
    v8::Local<Number> count = NanNew<Number>(data.count);

    v8::Local<v8::Value> argv[] = {
        count
    };

    js_callback->Call(NanNull(), 1, argv);
}

Upvotes: 3

Related Questions