V8 Multithread-Funktion

Ich schreibe ein Node-Plugin und habe Probleme beim Aufrufen eines V8-Funktionsobjekts aus einem C ++ - Arbeitsthread.

as @My-Plugin startet im Grunde genommen einen C ++ std :: -Thread und tritt mit WaitForSingleOject () in eine Warteschleife ein. Dies wird durch eine andere C ++ - App (ein X-Plane-Plugin) ausgelöst, die auf ein Bit des gemeinsam genutzten Speichers schreibt. Ich versuche, mein Node-Plugin zu aktivieren, wenn das von Windows freigegebene Ereignis signalisiert wird, und rufe dann eine von der Node-App registrierte JavaScript-Funktion auf, die die in X-Plane stammenden Daten an Node zurückgibt und die Web-Welt.

Ich habe es geschafft, eine JavaScript-Funktion zu registrieren und in C ++ aufzurufen, aber nur im Haupt-V8-Thread. Ich kann die Funktion scheinbar nicht über den std :: thread aufrufen.

Ich habe verschiedene Ansätze ausprobiert, Locker-Objekte (variabler Erfolg), Persistente Funktionen (hat nicht funktioniert), das Haupt-Isolat-Objekt speichern, das Isolat betreten / verlassen, aber wenn der Code irgendwann das Funktionsobjekt erreicht, ist er ungültig .

Ich erhalte unterschiedliche Ergebnisse, von Abstürzen bis zum Einfrieren, je nachdem, ob ich verschiedene Schließfach- und Entriegelungsobjekte erstelle.

Ich bin völlig neu in V8, daher bin ich mir nicht sicher, ob ich etwas richtig mache. Der fragliche Code lautet wie folgt:

Wenn irgendjemand helfen könnte, wäre ich auf ewig dankbar!

float* mem = 0;
HANDLE event = NULL;
Isolate* thisIsolate;

void readSharedMemory()
{
    //Isolate* isolate = Isolate::GetCurrent();
    //HandleScope scope(isolate);

    thisIsolate->Enter();
    v8::Locker locker(thisIsolate);
    v8::Isolate::Scope isolateScope(thisIsolate);
    //HandleScope scope(thisIsolate);        

    //v8::Local<Value> myVal = v8::String::NewFromUtf8(isolate, "Plugin world");
    v8::Local<Value> myVal = v8::Number::New(thisIsolate, *mem);

    // If it get's this far 'myFunction' is not valid
    bool isFun = myFunction->IsFunction();
    isFun = callbackFunction->IsFunction();

    v8::Context *thisContext = *(thisIsolate->GetCurrentContext());
    myFunction->Call(thisContext->Global(), 1, &(Handle<Value>(myVal)));
}

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

    /** Standard parameter checking code removed **/

    // Various attempts at saving a function object
    v8::Local<v8::Value> func = args[0];
    bool isFun = func->IsFunction();

    Handle<Object> callbackObject = args[0]->ToObject();

    callbackFunction = Handle<Function>::Cast(callbackObject);
    isFun = callbackFunction->IsFunction();

    // save the function call object - This appears to work
    myFunction = v8::Function::Cast(*callbackObject);
    isFun = myFunction->IsFunction();


    // Test the function - this works *without* the Unlocker object below
    v8::Local<Value> myVal = v8::String::NewFromUtf8(isolate, "Plugin world");   
    myFunction->Call(isolate->GetCurrentContext()->Global(), 1, &(Handle<Value>(myVal)));
}

void threadFunc()
{
    thisIsolate->Exit();
    // If I include this unlocker, the function call test above fails.
    // If I don't include it, the app hangs trying to create the locker in 'readSharedMemory()'
    //v8::Unlocker unlocker(thisIsolate); 

    event = OpenEventW(EVENT_ALL_ACCESS, FALSE, L"Global\\myEventObject");
    DWORD err = GetLastError();

    //thisIsolate = v8::Isolate::New();

    std::cout << "Hello from thread" << std::endl;
    bool runThread = true;

    while (runThread)
    {
        DWORD dwWaitResult;
        DWORD waitTime = 60000;
        dwWaitResult = WaitForSingleObject(event, waitTime);

        err = GetLastError();

        if (dwWaitResult == WAIT_TIMEOUT)
            runThread = false;

        // event has been signaled - continue
        readSharedMemory();    
    }
}

void init(Handle<Object> exports) 
{
    /** NODE INITILISATION STUFF REMOVED **/

    // save the isolate - Is this a safe thing to do?
    thisIsolate = Isolate::GetCurrent();
    //Launch a thread
    eventThread = std::thread(threadFunc);
}

Antworten auf die Frage(2)

Ihre Antwort auf die Frage