2016-05-02 39 views
4

我有一個多線程的C++插件,它做了一些後臺處理,我需要定期回調一下我在NodeJS服務器中編寫的Javascript函數。從多線程C++插件回調NodeJS Javascript函數

據我所知,這涉及到使用uv_async_send(),因爲它需要在主線程中執行,但到目前爲止我還無法弄清楚如何去做。

有沒有一個簡單的例子,我錯過了?

回答

14

最後,這是不是太困難,一旦我明白了的uv_ *函數做:

1)在插件暴露的功能,允許節點設置的Javascript CB將定期打電話回:

Callback* cbPeriodic; // keep cbPeriodic somewhere 
NAN_METHOD(setPeriodicCb) { 
    cbPeriodic = new Callback(info[0].As<Function>()); 
    //... 
} 

2)初始紫外線與uv_async_t實例,將在主線程通過UV當我們的工作者線程調用uv_async_send()

執行的功能
uv_async_t async; // keep this instance around for as long as we might need to do the periodic callback 
uv_loop_t* loop = uv_default_loop(); 
uv_async_init(loop, &async, asyncmsg); 

void asyncmsg(uv_async_t* handle) { 
    // Called by UV in main thread after our worker thread calls uv_async_send() 
    // I.e. it's safe to callback to the CB we defined in node! 
    Nan::HandleScope scope; 
    v8::Isolate* isolate = v8::Isolate::GetCurrent(); 
    Local<Value> argv[] = { v8::String::NewFromUtf8(isolate, "Hello world") }; 
    cbPeriodic->Call(1, argv); 
} 

3)從一個工人線程中調用uv_async_send,通過我們上面的異步例如,每當我們需要做的週期性回調

uv_async_send(&async); 

4)最後,當我們不再需要執行回調再以前更乾淨的東西了:

uv_close((uv_handle_t*) &async, NULL); 

附錄:

自從我寫這個答案我已經遇到其他問題終於瞭解到libuv一些教訓。爲了完整起見,你應該明白:

  • 除了uv_async_send

    所有 libuv功能可以從主循環線程調用! (我曾經看到它提到其他線程不是線程安全的,但是這太弱了)。例如,即使在主循環線程中也必須調用uv_async_inituv_close

  • 如果您的uv_async_t實例是動態分配的,請注意,您可能無法釋放內存,直到uv_close進行回調,讓您知道這樣做是安全的。

即:

auto async = new uv_async_t(); 
... 
uv_close((uv_handle_t*)async, [](uv_handle_t* handle) { 
    delete handle; 
});