2012-12-12 20 views
13

Utworzyłem nowy wątek poświęcony pętli uruchamiania libuv. Funkcja wątku wygląda mniej więcej tak:Czy wątek libuv jest bezpieczny?

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

Przyrost licznika ref utrzymuje wątek przy życiu i jest w stanie do przetwarzania zdarzeń libuv. Mam nadzieję, że uda mi się zakończyć pętlę uruchamiania, powodując wyjście wątku, wykonując uv_unref w głównym wątku.

Jednak podczas sprawdzania kodu źródłowego uv_ref nie widziałem żadnej gwarancji, że dostęp do zmiennej licznika odniesienia zostanie zsynchronizowany podczas dostępu równoczesnego. Dodatkowo nie widziałem żadnych wywołań wydajności w celu rezygnacji z kontroli systemu operacyjnego podczas pętli uruchamiania, co oznacza, że ​​program nie będzie współpracował dobrze z innymi procesami.

To prowadzi mnie do przekonania, że ​​nie używam libuv we właściwy sposób. Jeśli ktoś mógłby wyjaśnić, co robię źle, byłoby wspaniale!

Odpowiedz

30

Nie, libuv nie jest bezpieczny dla wątków w ten sposób. Powinieneś użyć uv_async, aby zasygnalizować zakończenie pętli. uv_async to jedyny bezpieczny dla wątków obiekt, który ma libuv.

To mogłoby wyglądać tak:

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

teraz z innego wątku można zasygnalizować tę pętlę na wyjściu poprzez wywołanie

uv_async_send(&exit_handle); 

Trzeba zadbać, aby nie wywołać uv_async_send() przed inny wątek zakończył konfigurowanie pętli i uchwyt uv_async. Najnowsza wersja libuv zawiera prymitywy synchronizacji uv_barrier, których możesz użyć; ale wersja libuv dostarczana z Node.js 0.8 nie obsługuje tego jeszcze, więc prawdopodobnie będziesz musiał użyć narzędzi pthread, aby to działało.

Na marginesie, wydajesz się wywoływać uv_ref i uv_unref z odwołaniem do pętli jako argumentem. W ostatnich wersjach libuv to się zmieniło, masz teraz uv_ref i uv_unref określony uchwyt. Aby uzyskać szczegółowe informacje, patrz uv.h.

Powiązane problemy