V8多线程功能

我正在编写Node插件,尝试从C ++工作线程调用V8函数对象时遇到问题。

我的插件基本上是启动一个C std :: thread并使用WaitForSingleOject()进入一个等待循环,这是由另一个C

应用程序(一个X-

Plane插件)向共享内存中写入数据触发的。我试图让我的Node插件在发出Windows共享事件信号时唤醒,然后调用我从node应用程序注册的JavaScript函数,这将依次将源自X-

Plane的数据传递回Node和网络世界。

我设法找出了如何注册JavaScript函数并从C ++调用它的方法,但是只能在V8主线程中进行。我似乎找不到从std :: thread调用函数的方法。

我尝试了各种方法,包括Locker对象(成功成功),Persistent函数(无法正常工作),保存主要隔离对象,输入/退出隔离对象,但是如果/当代码最终到达功能对象时,则无效。

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

我是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);

}

回答:

您可能需要一些libuv魔术才能使node.js / v8 线程从 另一个 线程执行回调。这将涉及:

  • 一个uv_async_t句柄,它充当v8主线程的唤醒调用:

    extern uv_async_t       async;

  • 一个uv_async_init结合了uv_async_t到V8默认循环调用:

    uv_async_init(uv_default_loop(), &async, async_cb_handler);

  • 还有一个事件处理程序,它将对 v8主线程 上的uvasync_t事件起作用:

    void async_cb_handler(uv_async_t *handle) {

    NotifInfo *notif;

    mutex::scoped_lock sl(zqueue_mutex);

    while (!zqueue.empty()) {

    notif = zqueue.front();

    handleNotification(notif);

    delete notif;

    zqueue.pop();

    }

    }

  • 最后,您可能还需要一个互斥锁保护的队列,以便能够将某些数据从c ++附加线程传递到Node / V8:

    extern mutex                   zqueue_mutex;

    extern std::queue zqueue;

  • 当您的 C ++线程 发生问题时,只需将新项目推送到互斥锁保护的队列中,然后调用uv_async_send即可唤醒V8的默认事件循环(所谓的“主线程”)以处理该项目(然后可以调用您的Javascript回调)

    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);

    }

(代码片段摘自用于OpenZWave的官方Node.JS插件)

以上是 V8多线程功能 的全部内容, 来源链接: utcz.com/qa/430491.html

回到顶部