nbind icon indicating copy to clipboard operation
nbind copied to clipboard

Trouble making threads work

Open vsantosu opened this issue 7 years ago • 2 comments

Hello there, this is an amazing project and I would like to use it for a native node addon.

Do somebody have an idea of how to make threading work? I know that the nbind::cbFunction function must be called within the same thread the parent function was called, so a setTimeout style functionality cannot be done easily.

I made the following experiment:

The Native Class:

#include <string>
#include <iostream>
#include <thread>
#include <chrono>
#include <nan.h>
#include "nbind/api.h"

class Utils
{
  nbind::cbFunction * asyncFactorialCB;

  public:
    Utils(){ }

    void asyncFactorial(int n, nbind::cbFunction &callback)
    {
        /* save callback function reference */
        Utils * self = this;
        self->asyncFactorialCB = new nbind::cbFunction(callback);

        /* a simple factorial thread using lambda */
        std::thread threadObj([n, self] {
            
            std::cout << "Start thread..." << std::endl;
            /* sleep thread for 2 seconds */
            std::this_thread::sleep_for(std::chrono::milliseconds(2000));
            /* do some work */
            int acu = n;
            for (int i = n; i > 1; i--)
            {
                acu = acu * (i - 1);
            }

            std::cout << "Result inside thread is: " <<acu<< std::endl;
            std::cout << "End thread..." << std::endl;
            std::cout << "Callback pointer: " << self->asyncFactorialCB << std::endl;

            /* callback javascript, CAUSES SEGMENTATION FAULT */
            (*self->asyncFactorialCB)(n);
        });
        /* detach from this thread */
        threadObj.detach();

        /* THIS HERE WORKS FINE */
        //(*self->asyncFactorialCB)(5555);
    }
};


#include "nbind/nbind.h"
#ifdef NBIND_CLASS
NBIND_CLASS(Utils)
{
    construct<>();
    method(asyncFactorial);
}
#endif

The Javascript code:

var nbind = require('nbind');

/* init native class */
const Utils = nbind.init().lib.Utils;

/* using the class */
let utl = new Utils();
let n = 5;

/* async example */
utl.asyncFactorial(n,(r)=>{
    console.log("Async Factorial of", n, "is", r);
});
console.log('JS', 'after calling async factorial');

/* prevents process from finish */
setInterval(()=>{
},5000);

Output:

Start thread...
JS after calling async factorial
Result inside thread is: 120
End thread...
Callback pointer: 0x1028033d0
Segmentation fault: 11

This is one of the most valuable use cases at the moment of writing an addon, specially for tools to process data in parallel. Any idea on how to make this work? Thanks in advanced!

vsantosu avatar May 16 '18 22:05 vsantosu

I have a similar issue, though I'm using libuv for threading (since that's what node is using). Seems like nbind is keeping track of a Scope or Isolate when code transitions from js to c++, so that doesn't exist when the main thread tries to go from c++ to js...

chad3814 avatar Jun 06 '18 22:06 chad3814

I have the same issue, I'll try out v8pp and see if that works.

zurp avatar Mar 28 '19 09:03 zurp