0

I have setup this repo which executes a node-addon-api thread safe function in a SWIG C++ class.

The thread in the SWIG C++ class is executed using the napi BlockingCallback like so :

// inside C++ thread
for (int i=0; i<4){
  sleep(1);
  int* value = new int( clock() );
  napi_status status = tsfn->BlockingCall( value, callback );
  if ( status != napi_ok ) { // Handle error }
}
// thread exits at this point

When I execute the javascript, the thread safe function is not executed until the thread has exited where the following code :

// setup the ThreadSafeFunction to call from the thread
let fp = libNapiNodejs.start(function () {
    console.log("JavaScript callback called with arguments", Array.from(arguments));
}, 5);
test.run(); // run the C++ thread in the SWIG module

// in the main thread, print out main every second
const id = setInterval(()=>console.log('main'),1000);
test.meetThread(); // wait for the C++ thread to exit
// the thread's queued function calls are executed now that the thread has exited

This is what is printed out when I run ./test/RunTest.js :

C++ Thread enter threadMain
thread loop 0 of 4
calling tsfn->BlockingCall
thread loop 1 of 4
calling tsfn->BlockingCall
thread loop 2 of 4
calling tsfn->BlockingCall
thread loop 3 of 4
calling tsfn->BlockingCall
C++ Thread exit threadMain
main
JavaScript callback called with arguments [ 48084 ]
JavaScript callback called with arguments [ 48218 ]
JavaScript callback called with arguments [ 48287 ]
JavaScript callback called with arguments [ 48356 ]
Matt
  • 509
  • 2
  • 14

1 Answers1

0

It seems that there are a few problems there. Firstly the main thread is being blocked by the meetThread call :

test.meetThread(); // wait for the C++ thread to exit

If this is removed, then the C++ callback to javascript executes immediately.

Now there is a garbage collection issue, because the test class instance looks like it is no longer in use - despite the face that its thread is still running in the background. To avoid this problem, we can use an interval timer to keep the object alive :

const id = setInterval(()=>{
  if (!test.running())
    clearInterval(id);
},1000);

Once the thread isn't running and the interval timer is cleared, the nodejs main thread exits as expected.

Here is the output :

C++ Thread enter threadMain
thread loop 0 of 10
calling tsfn->BlockingCall
JavaScript callback called with arguments [ 49627 ]
thread loop 1 of 10
calling tsfn->BlockingCall
JavaScript callback called with arguments [ 62402 ]
thread loop 2 of 10
calling tsfn->BlockingCall
JavaScript callback called with arguments [ 63585 ]
thread loop 3 of 10
calling tsfn->BlockingCall
JavaScript callback called with arguments [ 64822 ]
thread loop 4 of 10
calling tsfn->BlockingCall
JavaScript callback called with arguments [ 66171 ]
thread loop 5 of 10
calling tsfn->BlockingCall
JavaScript callback called with arguments [ 67321 ]
thread loop 6 of 10
calling tsfn->BlockingCall
JavaScript callback called with arguments [ 68454 ]
thread loop 7 of 10
calling tsfn->BlockingCall
JavaScript callback called with arguments [ 69584 ]
thread loop 8 of 10
calling tsfn->BlockingCall
JavaScript callback called with arguments [ 123351 ]
thread loop 9 of 10
calling tsfn->BlockingCall
C++ Thread exit threadMain
JavaScript callback called with arguments [ 124748 ]
Matt
  • 509
  • 2
  • 14