当前位置: 首页 > 面试题库 >

V8多线程功能

巫马刚洁
2023-03-14
问题内容

我正在编写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插件)



 类似资料:
  • 注意:“防多线程下载”功能需在“应用防护管理”中开启对应的防护(Web防护/Nginx自编译/RASP)才可使用。 线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开起好几个下载通道,所以占用的线程越多的话,占用的的带宽也就越多。带宽占用较多则会影响用户对网站的访问,影响网站的访问量。G01“防多线程下载”则通过限制下载的线程数量,避免单个用户占用带宽资源。 打开“防多线

  • 本文向大家介绍Shell脚本模拟多线程功能分享,包括了Shell脚本模拟多线程功能分享的使用技巧和注意事项,需要的朋友参考一下 说明:{} 这部分语句被放入后台作为一个子进程执行,这部分几乎是同时完成的,当fifo中10个空行读完后 while循环 继续等待 read 中读取fifo数据,当后台的10个子进程后,按次序排队往fifo输入空行,这样fifo中又有了数据,for语句继续执行。

  • 本文向大家介绍java多线程实现文件下载功能,包括了java多线程实现文件下载功能的使用技巧和注意事项,需要的朋友参考一下 多线程下载文件的思路: 1.首先获取到文件的总大小 获取文件大小的方式是通过网络读取,getContentLength()即可获取到文件的大小,使用RandomAccessFile()支持随机访问 2.根据所准备的线程数据,计算每一个线程需要下载的文件的大小 上图显示下载40

  • typora-copy-images-to: img 1. 多线程概述 人们在日常生活中,很多事情都是可以同时进行的。例如,一个人可以一边听音乐,一边打扫房间,可以一边吃饭,一边看电视。在使用计算机时,很多任务也是可以同时进行的。例如,可以一边浏览网页,一边打印文档,还可以一边聊天,一边复制文件等。计算机这种能够同时完成多项任务的技术,就是多线程技术。Java是支持多线程的语言之一,它内置了对多线

  • 使用 [Web Workers][web-workers]可以在系统级线程中运行JavaScript。 多线程Node.js 在 webPreferences中将 n​​odeIntegrationInWorker选项设置为 true,可以在Electron的Web Workers中使用Node.js功能: 1 let win = new BrowserWindow({ 2 webPreferen

  • If you use Casbin in a multi-threading manner, you can use the synchronized wrapper of the Casbin enforcer: https://github.com/casbin/casbin/blob/master/enforcer_synced.go (GoLang) and https://github.