2012-02-28 14 views
13

Considere que tengo lamba foo que solo hace algunas cosas y no necesita devolver nada. Cuando hago esto:std :: async no engendrará un nuevo hilo cuando no se almacena el valor de retorno

std::future<T> handle = std::async(std::launch::async, foo, arg1, arg2); 

todo funciona bien y el Lamba se dio lugar en un nuevo hilo. Sin embargo, cuando no almaceno el std::future que devuelve el std::async, el foo se ejecutará en el hilo principal y lo bloqueará.

std::async(std::launch::async, foo, arg1, arg2); 

¿Qué es lo que falta aquí?

+5

Quizás el '' 'future''' devuelto por' '' async''' se destruye inmediatamente. No me sorprendería si '' 'el destructor' future''' tiene una espera implícita adentro. –

Respuesta

16

De just::threaddocumentation:

Si la política es std::launch::asyncINVOKE(fff,xyz...) posteriormente ejecuta en su propio hilo. El std::future devuelto estará listo cuando se complete este subproceso, y contendrá el valor devuelto o la excepción lanzada por la invocación de función. El destructor del último objeto futuro asociado con el estado asíncrono del std::future devuelto se bloqueará hasta que el futuro esté listo.

En

std::async(std::launch::async, foo, arg1, arg2); 

El futuro devuelto no se le asigna ninguna parte y sus bloques destructor hasta foo acabados.

4

Me gustaría agregar un enlace a un artículo de Herb Sutter en async and ~future en el que argumenta que los futuros nunca deben bloquearse.

+0

No es un artículo sino una propuesta. Aparte de eso, sí, hacer un bloque '~ future()' fue un error. – Xeo

+2

~ future() en realidad no bloquea por defecto. Solo bloquea cuando se devuelve desde std :: async, porque async asigna un estado de bloqueo a futuro y ~ future() tiene que liberarlo. –

0

¿Por qué bloquear?

  1. std::async(); vuelve std::futureobjeto temporal
  2. temporal objeto se destruye inmediatamente, llamando desctructor.
  3. std::future destructor está bloqueando. Es malo y problemático

¿Por qué asignar está bien?

Al asignar a una variable, el objeto devuelto no se destruye inmediatamente, sino más tarde, hasta el final del alcance de su código de llamada.

Ejemplo de código: main1 está bien. main2 y main3 están bloqueando de manera equivalente el hilo principal.

void forever() { 
    while (true); 
} 

void main1() { 
    std::future<void> p = std::async(std::launch::async, forever); 
    std::cout << "printing" << std::endl; // can print, then forever blocking 
} 

void main2() { 
    std::async(std::launch::async, forever); 
    std::cout << "printing" << std::endl; // forever blocking first, cannot print 
} 

void main3() { 
    {std::future<void> p = std::async(std::launch::async, forever);} 
    std::cout << "printing" << std::endl; // forever blocking first, cannot print 
} 

Tome un vistazo a cplusplus.com

valor de retorno de std :: asíncrono Cuando se selecciona lanzamiento :: asíncrono, regresó el futuro está ligado al extremo del hilo creado, incluso si nunca se accede a su estado compartido: en este caso, su destructor se sincroniza con el retorno de fn. Por lo tanto, el valor de retorno no debe descartarse para el comportamiento asincrónico , incluso cuando fn se anula.

Cuestiones relacionadas