2012-02-28 11 views
13

Considera che ho lamba foo che fa solo alcune cose e non ha bisogno di restituire nulla. Quando faccio questo:std :: async non genera un nuovo thread quando il valore di ritorno non viene memorizzato

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

tutto funziona bene e la Lamba sarà deposto le uova in un nuovo thread. Tuttavia, quando non ripongo lo std::future che restituisce il std::async, il foo verrà eseguito nel thread principale e lo bloccherà.

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

Cosa mi manca qui?

+5

Forse il '' '' ''' restituito da' '' async''' viene immediatamente distrutto. Non mi sorprenderebbe se il distruttore '' '' '' '' 'abbia un'attesa implicita all'interno. –

risposta

16

Da just::threaddocumentation:

Se la politica è std::launch::async poi corre INVOKE(fff,xyz...) sul proprio thread. Il reso std::future sarà pronto quando questo thread è completo e terrà il valore di ritorno o l'eccezione generata dal richiamo della funzione. Il distruttore dell'ultimo oggetto futuro associato allo stato asincrono dello std::future restituito verrà bloccato finché il futuro non sarà pronto.

In

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

Il futuro restituito non è assegnata nessuna parte ed i suoi blocchi destructor fino foo finiture.

4

Vorrei aggiungere un collegamento a un articolo di Herb Sutter su async and ~future in cui sostiene che il futuro non dovrebbe mai bloccare.

+0

Non è un articolo ma una proposta. A parte questo, sì, rendere il blocco '~ future()' è stato un errore. – Xeo

+2

~ future() in realtà non blocca per impostazione predefinita. Blocca solo quando viene restituito da std :: async, perché async assegna uno stato di blocco a futuro e ~ future() deve rilasciarlo. –

0

Perché bloccare?

  1. std::async(); rendimenti std::futureoggetto temporaneo
  2. temporanea oggetto viene distrutto immediatamente, chiamando desctructor.
  3. std::future Il distruttore sta bloccando. È cattivo e problematico.

Perché l'assegnazione è ok?

Assegnando a una variabile, l'oggetto restituito non viene distrutto immediatamente, ma in un secondo momento, fino alla fine dell'ambito del codice chiamante.

Codice Esempio: main1 è ok. main2 e main3 bloccano in modo equivalente il thread principale.

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 
} 

Date un'occhiata a cplusplus.com

valore di ritorno di std :: asincrona Quando si seleziona il lancio :: asincrono, il futuro restituito è legata alla fine del thread creato, anche se il suo stato condiviso non è mai raggiunto: in questo caso, il suo distruttore si sincronizza con il ritorno di fn. Pertanto, il valore restituito non deve essere ignorato per il comportamento asincrono , anche quando fn restituisce void.

Problemi correlati