2012-12-12 19 views
13

Ho creato una nuova discussione dedicata a un ciclo di esecuzione di libuv. La funzione di filo simile a questa:Il thread libuv è sicuro?

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

L'arbitro incremento del contatore mantiene il filo vivo e in uno stato di elaborare libuv eventi. Spero di riuscire a far terminare il ciclo di esecuzione, causando così l'uscita del thread, eseguendo uv_unref sul thread principale.

Tuttavia, durante l'ispezione del codice sorgente uv_ref non ho visto alcuna garanzia che l'accesso alla variabile del contatore di riferimento sarebbe stato sincronizzato durante l'accesso simultaneo. Inoltre non ho visto alcun richiamo di rendimento per abbandonare il controllo del sistema operativo durante il ciclo di esecuzione, il che significa che il programma non coopererà bene con altri processi.

Questo mi porta a credere che non sto usando libuv nel modo giusto. Se qualcuno potesse spiegare cosa sto sbagliando, sarebbe fantastico!

risposta

30

No, libuv non è sicuro da thread in questo modo. Dovresti usare uv_async per segnalare al loop di uscire. uv_async è l'unica funzionalità thread-safe che ha libuv.

Sarebbe simile a questa:

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

Ora dal l'altro thread è possibile segnalare questo ciclo per uscire chiamando

uv_async_send(&exit_handle); 

È necessario fare attenzione a non chiamare uv_async_send() prima della l'altro thread ha finito di impostare il ciclo e l'handle di uv_async. La versione recente di libuv include le primitive di sincronizzazione uv_barrier che è possibile utilizzare; ma la versione di libuv fornita con Node.js 0.8 non supporta ancora questo, quindi probabilmente è necessario utilizzare le funzionalità di pthread per farlo funzionare.

Su una nota a margine, sembra che chiami uv_ref e uv_unref con un riferimento di ciclo come argomento. Nelle versioni recenti di libuv questo è cambiato, ora si suppone che sia uv_ref e uv_unref un handle specifico. Vedi uv.h per i dettagli.