V8多线程函数 我正在编写一个节点插件,并且试图从C++工作线程调用V8函数对象时遇到问题。 我的插件基本上启动了一个C++ STD::线程,并使用WaIfFutSnLoojjEd()进入一个等待循环,这是由一个不同的C++应用程序(X-Payon插件)触发的,它写入了一个共享内存。我试图让我的节点插件在Windows共享事件发出信号时唤醒,然后调用我从节点应用程序注册的JavaScript函数,该函数将把源于X平面的数据传递回节点和web世界 我已经设法解决了如何注册一个JavaScript函数,并从C++调用它,但只在主V8线程中登记。我似乎找不到从std::线程调用函数的方法

V8多线程函数 我正在编写一个节点插件,并且试图从C++工作线程调用V8函数对象时遇到问题。 我的插件基本上启动了一个C++ STD::线程,并使用WaIfFutSnLoojjEd()进入一个等待循环,这是由一个不同的C++应用程序(X-Payon插件)触发的,它写入了一个共享内存。我试图让我的节点插件在Windows共享事件发出信号时唤醒,然后调用我从节点应用程序注册的JavaScript函数,该函数将把源于X平面的数据传递回节点和web世界 我已经设法解决了如何注册一个JavaScript函数,并从C++调用它,但只在主V8线程中登记。我似乎找不到从std::线程调用函数的方法,c++,node.js,multithreading,v8,node.js-addon,C++,Node.js,Multithreading,V8,Node.js Addon,我尝试过各种方法,Locker对象(变量success),持久函数(不起作用),保存主隔离对象,输入/退出隔离,但是如果/当代码最终到达函数对象时,它是无效的 我得到了不同的结果,从崩溃到冻结,这取决于我是否创建了各种锁存器和解锁器对象 我对V8完全是新手,所以我不确定自己做得是否正确。有关守则如下: 如果有人能帮上忙,我将永远感激 float* mem = 0; HANDLE event = NULL; Isolate* thisIsolate; void readSharedMemory(

我尝试过各种方法,Locker对象(变量success),持久函数(不起作用),保存主隔离对象,输入/退出隔离,但是如果/当代码最终到达函数对象时,它是无效的

我得到了不同的结果,从崩溃到冻结,这取决于我是否创建了各种锁存器和解锁器对象

我对V8完全是新手,所以我不确定自己做得是否正确。有关守则如下:

如果有人能帮上忙,我将永远感激

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);
}
float*mem=0;
句柄事件=NULL;
隔离*这个隔离;
void readSharedMemory()
{
//隔离*隔离=隔离::GetCurrent();
//手镜范围(隔离);
thisIsolate->Enter();
v8::储物柜(该隔离);
v8::Isolate::Scope isolateScope(thisIsolate);
//手镜范围(本标准);
//v8::Local myVal=v8::String::NewFromUtf8(隔离“插件世界”);
v8::Local myVal=v8::Number::New(thisIsolate,*mem);
//如果到目前为止,“myFunction”无效
bool isFun=myFunction->IsFunction();
isFun=callbackFunction->IsFunction();
v8::Context*thisContext=*(thisIsolate->GetCurrentContext());
myFunction->Call(thisContext->Global(),1,&(Handle(myVal));
}
无效注册表回调(常量函数回调信息和参数)
{
隔离*隔离=隔离::GetCurrent();
v8::储物柜(隔离);
手镜范围(隔离);
/**标准参数检查代码已删除**/
//保存函数对象的各种尝试
v8::Local func=args[0];
bool isFun=func->IsFunction();
Handle callbackObject=args[0]->ToObject();
callbackFunction=Handle::Cast(callbackObject);
isFun=callbackFunction->IsFunction();
//保存函数调用对象-这似乎有效
myFunction=v8::Function::Cast(*callbackObject);
isFun=myFunction->IsFunction();
//测试函数-这在没有下面的解锁对象的情况下工作
v8::Local myVal=v8::String::NewFromUtf8(隔离“插件世界”);
myFunction->Call(隔离->GetCurrentContext()->Global(),1,&(句柄(myVal));
}
void threadFunc()
{
thisIsolate->Exit();
//如果包含此解锁器,则上述函数调用测试将失败。
//如果我没有包括它,应用程序将挂起,尝试在“readSharedMemory()中创建锁柜”
//v8::解锁器解锁器(thisIsolate);
event=OpenEventW(event_ALL_ACCESS,FALSE,L“Global\\myEventObject”);
DWORD err=GetLastError();
//thisIsolate=v8::Isolate::New();

std::cout您可能需要一点
libuv
魔法才能让main node.js/v8线程从另一个线程执行回调。这将涉及:

  • 作为v8主线程的唤醒信号:

    extern uv_async_t       async;
    
  • 一个
    uv\u async\u init
    调用,它将uv\u async\t绑定到V8默认循环:

    uv_async_init(uv_default_loop(), &async, async_cb_handler);
    
  • 以及一个事件处理程序,用于处理v8主线程上的uvasync_t事件:

  • 最后,您可能还需要一个互斥保护队列,以便将一些数据从C++ ADDON线程传递到No/V8:< /P>
    extern mutex                   zqueue_mutex;
    extern std::queue<NotifInfo *> zqueue;
    

(代码片段摘自)

谢谢,如果有机会,我会尝试一下。同时我会把它标记为答案。
extern mutex                   zqueue_mutex;
extern std::queue<NotifInfo *> zqueue;
void ozw_watcher_callback(OpenZWave::Notification const *cb, void *ctx) {
    NotifInfo *notif = new NotifInfo();
    notif->type   = cb->GetType();
    notif->homeid = cb->GetHomeId();
    ...
    mutex::scoped_lock sl(zqueue_mutex);
    zqueue.push(notif);
    uv_async_send(&async);
}