2017-03-07 3 views
5

den folgenden Quellcodestd :: Futures und Ausnahme

#include <thread> 
#include <future> 
#include <iostream> 
#include <string> 
#include <chrono> 

int main() { 

    auto task = std::async(std::launch::async, [] {  
     std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 
     throw std::runtime_error("error"); 
    }); 


    try { 
     while (task.wait_for(std::chrono::seconds(0)) !=std::future_status::ready) 
     { 
      std::cout << "Not ready: " << std::endl; 
     } 
     task.get(); 
    } 
    catch (const std::exception& e) 
    { 
     std::cout << "Valid: " << task.valid() << std::endl; 
    } 

} 

Da ich würde erwarten, dass das Programm wird Antwort mit Valid: 0. Mit g ++ 6.2.0 ist dies der Fall. Bei Verwendung von MS VS2015 Version 14.0.25431.01 Update 3 lautet die Antwort jedoch Valid: 1. Der Status der Zukunft wird nicht ungültig, nachdem die Ausnahme an den Hauptthread weitergegeben wurde. Ist das ein Fehler oder laufe ich hier auf undefiniertes Verhalten?

Antwort

1

Ich scheint ein Fehler zu sein.

Nach std::future::get documentation sollte false nach einem Anruf an get zurückgeben.

Jeder freigegebene Status wird freigegeben. valid() ist false nach einem Aufruf dieser Methode.

ein wenig in VC++ Implementierung von get Graben, gibt es einen Fehler gibt:

virtual _Ty& _Get_value(bool _Get_only_once) 
     { // return the stored result or throw stored exception 
     unique_lock<mutex> _Lock(_Mtx); 
     if (_Get_only_once && _Retrieved) 
      _Throw_future_error(
       make_error_code(future_errc::future_already_retrieved)); 
     if (_Exception) 
      _Rethrow_future_exception(_Exception); 
     _Retrieved = true; 
     _Maybe_run_deferred_function(_Lock); 
     while (!_Ready) 
      _Cond.wait(_Lock); 
     if (_Exception) 
      _Rethrow_future_exception(_Exception); 
     return (_Result); 
     } 

grundsätzlich _Retreived auch true eingestellt werden sollte, wenn _Exception eine exception_ptr hält. Zum Zeitpunkt des Wurfes wird diese Variable niemals gesetzt. es scheint, dass, wenn sie es getestet haben, sie nicht für eine fertige Zukunft, nur für nicht bereit Zukunft getestet haben, weil letztere diesen Fehler nicht zeigen wird.

+0

Gibt es einen Workaround? Wenn ich die wait_for-Anweisung lösche, funktioniert es wie erwartet, aber in meinem Produktionscode benötige ich einen Programmfluss ähnlich der Beispielquelle. – IcePic

+0

@IcePic kann stattdessen "Nebenläufigkeit :: Aufgabe" verwenden. Unter VC++ ist 'std :: async' ohnehin ein dünner Wrapper um Aufgaben. –