Node.js C ++ Addon:线程 [英] Node.js C++ Addon: Threading

查看:456
本文介绍了Node.js C ++ Addon:线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为Node.js(wxWidgets)写一个GUI插件,我想在自己的线程中运行GUI循环,因为我不认为将它与Node的主线程和事件合并是个好主意循环。

I'm writing a GUI addon for Node.js (wxWidgets) and I want to run the GUI loop in an own thread as I don't think it would be a good idea to merge it with Node's main thread and event loop.

但我不知道如何创建一个新的线程。我得到它运行与 uv_queue_work()。但它不会为GUI创建一个独占线程,但使用Node的线程池。这可能是一个坏主意,因为工作者将在整个运行时保持。 (不确定这一点)

However I'm not sure how to create a new thread. I got it running with uv_queue_work(). But it will not create an exclusive thread for the GUI but use Node's thread pool. And this might be a bad idea since the worker will stay during the whole runtime. (Not sure about this)

我也可以使用wxWidgets的 wxThread 我在libuv git master中找到了一个新函数 uv_thread_create 。不知道如何使用它,因为没有描述,此外它还没有在Node.js稳定版本中。

I could also use wxWidgets' wxThread, works, too. And I found a new function uv_thread_create in libuv git master. No idea how to use that as there is no description and besides it is not yet available in Node.js stable build.

我的问题:什么是标准的方式创建一个多线程的Node.js Addon,如果有的话?我看过其他项目,但只能找到使用libuv的短期工作线程。

My question: What is the "standard" way to create a multi-threaded Node.js Addon, if any? I looked at other projects but could only find short-running worker threads using libuv.

推荐答案

答案是,使用由Nodejs管理的后台线程,通过将您的工作提交到uv事件队列,然后让nodejs担心如何创建和管理线程。

The answer is that you typically want to use the background threads managed by Nodejs by submitting your work to the uv event queue, and then let nodejs worry about how to create and manage threads.

这是node.js v0.10手册中缺少的。

below is the boilerplate example which is missing from the node.js v0.10 manual.

struct Baton
{
    // we need this structure to interact with the uv
    // the uv_work_t must be the initial element and should store 
    // the callback function to be useful, but the rest
    // is user defined depending on what is needed to actually do the work.
    uv_work_t                    request;
    v8::Persistent<v8::Function> callback;
    // Add more elements to the structure as needed
    int                          countdown;
};


static void AsyncTestWork (uv_work_t* req);
static void AsyncTestAfter(uv_work_t* req,int status);
static Handle<Value> AsyncTestPrep(const Arguments& args) 
{
    HandleScope scope;
    if (args.Length() != 1) {
        ThrowException(Exception::TypeError(String::New("Wrong number of arguments -- needs (callback)")));
        return scope.Close(Undefined());
    }

    if (!args[0]->IsFunction()) {
        ThrowException(Exception::TypeError(String::New("Wrong type of arguments -- needs (callback)")));
        return scope.Close(Undefined());
    }

    v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[0]);

    Baton* baton = new Baton();
    baton->request.data = baton;
    baton->callback = v8::Persistent<v8::Function>::New(callback);
    baton->countdown = 3;

    uv_queue_work(uv_default_loop(), &baton->request, AsyncTestWork, AsyncTestAfter);

    return scope.Close(v8::Undefined());
}


static void AsyncTestWork (uv_work_t* req)
{
    // This method will run in a seperate thread where you can do 
    // your blocking background work.
    // In this function, you cannot under any circumstances access any V8/node js
    // valiables -- all data and memory needed, MUSt be in the Baton structure
    Baton* baton = static_cast<Baton*>(req->data);
    sleep(6); // some fictional work, delaying the return....
    baton->countdown -= 1;  // my actual work in this 
}

static void AsyncTestAfter(uv_work_t* req,int status)
{
    // This is what is called after the 'Work' is done, you can now move any data from 
    // Baton to the V8/Nodejs space and invoke call back functions

    Baton* baton = static_cast<Baton*>(req->data);

    v8::Handle<v8::Value> argv1[] = { v8::Null(), Number::New(baton->countdown) };
    v8::Handle<v8::Value> argv2[] = { v8::Null(), Number::New(23) };

    v8::TryCatch try_catch;
       // Call back to the JS function, you can make as many/few callbacks  
       // as you need, they just go on the event loop queue for now.
       // Note: that it is mostly customary to call the callback  
       // function just (exactly) which is probably what you want  
       // to do to avoid confusing your users if you make a public api
       baton->callback->Call(v8::Context::GetCurrent()->Global(), 2, argv1);
       baton->callback->Call(v8::Context::GetCurrent()->Global(), 2, argv2);
    if (try_catch.HasCaught()) {
        node::FatalException(try_catch);
    }

    if (baton->countdown > 0) {
        // resubmit the worker for yet more work
        uv_queue_work(uv_default_loop(), &baton->request, AsyncTestWork, AsyncTestAfter);
    } else {
        // we are finished, clean up and be done
        baton->callback.Dispose();
        delete baton;
    }
}


void init(Handle<Object> exports) 
{

  exports->Set(String::NewSymbol("myAsyncTestFunction"),
               FunctionTemplate::New(AsyncTestPrep)->GetFunction());

}

这篇关于Node.js C ++ Addon:线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆