2013-01-08 9 views
8

La mia comprensione è che quando un'operazione asincrona genera un'eccezione, verrà propagata a un thread che chiama std::future::get(). Tuttavia, quando tale thread chiama std::future::wait(), l'eccezione non viene immediatamente propagata, ma verrà lanciata in seguito a una chiamata a std::future::get().Propagazione di eccezioni e std :: future

Tuttavia, in uno scenario del genere, che cosa dovrebbe accadere a tale eccezione se l'oggetto futuro esce dall'ambito dopo una chiamata a std::future::wait(), ma prima di una chiamata a std::future::get()?

Per chi è interessato, ecco un semplice esempio. In questo caso, l'eccezione viene silenziosamente gestita dal pacchetto filo/futuro:

#include "stdafx.h" 
#include <thread> 
#include <future> 
#include <iostream> 

int32_t DoWork(int32_t i) 
{ 
    std::cout << "i == " << i << std::endl; 
    throw std::runtime_error("DoWork test exception"); 
    return 0; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    auto f = std::async(DoWork, 5); 
    try 
    { 
     //f.get();  // 1 - Exception does propagate. 
     f.wait();  // 2 - Exception does NOT propagate. 
    } 
    catch(std::exception& e) 
    { 
     std::cout << e.what() << std::endl; 
     return -1; 
    } 
    return 0; 
} 
+0

I _think_ non succede nulla all'eccezione, semplicemente viene ignorato. (Ma non sono abbastanza familiare con questo per essere sicuro.) – Mat

+1

Immagino sia importante notare che le eccezioni sono propagate attraverso i thread di 'std :: exception_ptr's. Quindi al sistema l'eccezione sembra essere catturata e gestita fino a quando il meccanismo di propagazione non decide di ricominciare. –

risposta

12

È ignorato e scartato, proprio come se si wait() per un valore, ma mai get() esso.

wait() dice semplicemente "bloccare fino a quando il futuro è pronto", essere pronto con un valore o un'eccezione. Spetta al chiamante effettivamente il valore (o eccezione) get(). Di solito ti basta usare get(), che aspetta comunque.

+0

Gah! Comprerò questo, ma è confuso, specialmente se lo std :: future creato da std :: async ha un tipo di risultato nullo. Chiamare get() per un simile futuro sembra strano. – Bukes

+4

@Bukes: Heh l'ho visto. Ma non pensare a 'future ' come "un risultato di' T' ", pensala come" il risultato del calcolo di 'T'", che ovviamente potrebbe essere un'eccezione. – GManNickG

+0

@GManNickG cosa succede se la funzione restituisce void allora non pensi che abbia senso chiamare wait() invece di get() – Kapil

0

vs2012 \ VC11 \ crt \ future.cpp

c'è un errore con il

static const char *const _Future_messages[] = 
{ // messages for future errors 
"broken promise", 
"future already retrieved", 
"promise already satisfied", 
"no state" 
}; 

questo codice generato un acceso non valida per "_Future_messages" perché _Mycode.value() ritorno 4.

const char *__CLR_OR_THIS_CALL what() const _THROW0() 
    { // get message string 
    return (_Get_future_error_what(_Mycode.value())); 
    } 

// esempio di codice

std::future<int> empty; 
try { 
    int n = empty.get(); 
} catch (const std::future_error& e) { 
    const error_code eCode = e.code(); 
    char *sValue = (char*)e.what(); 
    std::cout << "Caught a future_error with code " << eCode.message() 
       << " - what" << sValue << endl; 
}