1

I am making and addon (to nodejs). One of the functions that I have is responsible of doing fast algorithms with audio that arrives. My objective is to do that algorithms in a thread. This is a resume of that function:

void buffering(const FunctionCallbackInfo<v8::Value>& args) {
    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope(isolate);

    int size = args[1]->NumberValue();
    int final_read = args[2]->NumberValue();
    int inicio_read = args[3]->NumberValue();
    int client_id = args[4]->NumberValue();

    Local<Object> bufferObj = args[0]->ToObject();

    buf = node::Buffer::Data(bufferObj);
    char mini_buf[80000];//char mini_buf[4096];
    memcpy(mini_buf, buf, size);
    //To implement a thread
    int teste_buf = Julius[client_id].Audio_Buffering(mini_buf, size, final_read, inicio_read, client_id);

    //(....returns to nodejs...)
}

If the Audio_Buffering was only executed only one time, I could do in this way:

std::thread t[num__threads];
t[client_id] = std::thread(&SREngineJulius::Audio_Buffering, &Julius[client_id], mini_buf, size, final_read,inicio_read,client_id);

It happens that, this function is executed as long the audio is coming (because of the events in server). So my objective is to put that executions in a thread. Could be the same? If not how can i make that happen?

Fozi
  • 4,973
  • 1
  • 32
  • 56
carduh
  • 529
  • 1
  • 4
  • 13
  • 1
    The question is unclear, and the code is not clairifying. What do you mean by 'reuse a thread'? If you mean use the same C++ `thread` object, this is impossible. If you want to execute another function in already created thread, this is possible if your thread implements some sort of message queue, and performs various actions based on the next message in queue. – SergeyA Oct 22 '15 at 13:56
  • 1
    @carduh: Could you please rephrase your question and clarify your goal ? In the mean time, all I can suggest is that you have a look at [Thread pooling in C++11](https://stackoverflow.com/questions/15752659/thread-pooling-in-c11). – maddouri Oct 22 '15 at 14:00
  • @SergeyA my objective is to run `Audio_Buffering` always in a thread. But because the server will trigger many events of buffering (until is ended) I am studying alternatives to keep the routine `Audio_Buffering` in a thread. One alternative, I gess is to create new threads as long the buffering events of server is triggered. But could be a good solution? – carduh Oct 22 '15 at 14:01
  • Yeah, you need a thread (possibly a pool) with message queue. – SergeyA Oct 22 '15 at 14:04
  • I agree with with @SergeyA. Depending on the number of simultaneous calls and processing time, you might also want to consider [`std::async`](http://en.cppreference.com/w/cpp/thread/async)... – maddouri Oct 22 '15 at 14:13

1 Answers1

0

Your call is processed in the main thread and is therefore blocking the JS from running. You should be doing the work in an extra thread, but this will fundamentally change the way your function works right now.

Essentially this will split your function in three parts:

  1. Validation: Copy the input data (parameters, buffer data) out of the V8 structures and off the stack. You can't call any V8 functions in your worker thread. As your function will now be asynchronous you will also need to pass at least one callback to it.

  2. Work: Do the work in your worker thread and store the output somewhere.

  3. Resolve: Back in the main thread, import the output into V8 structures and call the callback.

Details:

  1. I won't explain you how to get your data out, it seems like you solved that problem. You have to store it somewhere out of V8 and your current stack frame, I suggest a structure that you create with std::make_shared and fill in while you validate the input. Store the Callback(s) as v8::Persistent<v8::Function>; You will also need to store the isolate.

  2. Start your thread in your prefered way. Use thread pool or not. Don't use std::async as you are not allowed to wait for it. Pass the pointer to your data to it and let it do the work.

  3. From your worker thread you need to get back in the main thread. You have to do this using uv_async_send from uv.h (see also uv_async_init and uv_close). In the main thread, in a v8::HandleScope, create a v8::Local<v8::Function> and call it.

Fozi
  • 4,973
  • 1
  • 32
  • 56