2012-12-12 11 views
13

私はlibuv実行ループ専用の新しいスレッドを作成しました。スレッド関数は次のようなものになります。libuvスレッドは安全ですか?

void thread_function() 
{ 
    uv_loop_t *loop = uv_loop_new(); 
    uv_ref(loop); 
    uv_run(loop); 
} 

を参照カウンタの増分は生きているとlibuvイベントを処理する状態でスレッドを保持します。 uv_unrefをメインスレッドで実行して、実行ループを終了させて​​スレッドを終了させたいと考えています。

しかし、uv_refソースコードを調べると、参照カウンタ変数へのアクセスが同時アクセス中に同期される保証はありませんでした。さらに、実行ループ中にオペレーティングシステムへの制御を放棄するための利回りコールは見られませんでした。つまり、プログラムは他のプロセスとうまく連携しません。

これは正しい方法でlibuvを使用していないと私に信じています。誰かが私が間違っていることを説明できるなら、それは素晴らしいことでしょう!

答えて

30

いいえ、libuvはこのようにスレッドセーフではありません。ループを終了するように通知するには、uv_asyncを使用する必要があります。 uv_asyncは、libuvが持つ唯一のスレッドセーフな機能です。

それはこのようになります:

uv_async_t exit_handle; 

void exit_async_cb(uv_async_t* handle, int status) { 
    /* After closing the async handle, it will no longer keep the loop alive. */ 
    uv_close((uv_handle_t*) &exit_handle, NULL); 
} 

void thread_function() { 
    uv_loop_t *loop = uv_loop_new(); 
    /* The existence of the async handle will keep the loop alive. */ 
    uv_async_init(loop, &exit_handle, exit_async_cb); 
    uv_run(loop); 
} 

を今、あなたは出口までこのループを知らせることができ、他のスレッドから

uv_async_send(&exit_handle); 

を呼び出すことによって、あなたは前に uv_async_send()を呼び出さないように注意してくださいする必要があります他のスレッドは、ループとuv_asyncハンドルの設定を完了しました。 libuvの最近のバージョンには、使用できる同期プリミティブ uv_barrierが含まれています。 Node.js 0.8に同梱されているlibuvはこれをまだサポートしていないので、おそらくpthread機能を使ってこの作業を行う必要があります。

ループノートを引数としてuv_refuv_unrefを呼び出しているようです。 libuvの最近のバージョンでは、これが変更されました。あなたは今やuv_refuv_unrefという特定のハンドルになっています。詳細は、uv.hを参照してください。

関連する問題