2015-11-24 4 views
8

Nach cppreference nach std::future::get Aufruf:std :: Zukunft noch gültig nach get() aufgerufen wird (die eine Ausnahme auslöst)

gültig() falsch ist nach einem Aufruf dieser Methode.

Zusätzlich aus cplusplus.com:

Sobald der gemeinsamen Staat bereit ist, hebt die Blockierung der Funktion und kehrt (oder wirft) ihren gemeinsamen Zustand freigegeben wird. Dies macht das zukünftige Objekt nicht mehr gültig: Diese Memberfunktion soll höchstens einmal für jeden zukünftigen gemeinsamen Zustand aufgerufen werden.

Und unter Ausnahme Sicherheit:

Die Funktion der Ausnahme in dem freigegebenen Zustand gespeichert wirft, wenn der Anbieter, indem es auf eine Ausnahme es bereit macht. Beachten Sie, dass in diesem Fall eine Basisgarantie angeboten wird, wobei das zukünftige Objekt modifiziert wird, um keine gültige Zukunft mehr zu sein (was selbst ein gültiger Zustand für ein Objekt dieses Typs ist, trotz seines Namens).

Weder Beschreibung macht einen Unterschied zwischen einem Aufruf get, die einen Wert im Vergleich zu einer zurückgibt, die eine Ausnahme in Bezug auf die Ungültigkeit des zukünftigen Objekt wirft.

das beschriebene Verhalten jedoch nicht das, was ich mit diesem Beispielcode zu sehen bin:

#include <chrono> 
#include <future> 
#include <iostream> 
#include <stdexcept> 


int foo() 
{ 
    throw std::runtime_error("foo exception"); 
} 


int main() 
{ 
    std::future<int> futInt; 

    futInt = std::async(std::launch::async, []() { return foo(); }); 

    while(!(futInt.valid() && futInt.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready)) 
     ; 

    if(futInt.valid()) 
    { 
     int val; 
     try 
     { 
      val = futInt.get(); 
     } 
     catch(const std::exception& e) 
     { 
      std::cout << e.what() << std::endl; 
     } 
    } 

    if(futInt.valid()) 
    { 
     std::cout << "This is TOTALLY UNEXPECTED!!!" << std::endl; 
    } 
    else 
    { 
     std::cout << "This is expected." << std::endl; 
    } 

    return 0; 
} 

Der Ausgang ich sehe, ist:

foo exception 
This is TOTALLY UNEXPECTED!!! 

I von Visual Studio Premium 2013 bin mit, Version 12.0.30501.00 Update 2. Ist das ein Fehler beim Compiler oder eigentlich das Verhalten bei einer Exception? Ich war nicht in der Lage, irgendwelche Fehlerberichte diesbezüglich zu finden, also war ich nicht sicher, ob es erwartetes Verhalten war.

Bearbeiten - <Zukunft> Umsetzung Untersuchung

Graben in die std::future Umsetzung ein wenig, das _Associated_state Objekt _Retrieved = true; markiert NACH Prüfung und werfen die zugehörige Ausnahme (falls vorhanden):

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

Meine Vermutung ist, dass die Ausnahmeprüfung und _Retrieved = true; ausgetauscht werden sollte - das Objekt sollte sofort Als Erstes wird die Abfrage (nach der _Get_only_once Prüfung) gesetzt und dann sollte alle andere Logik folgen. Ergo, Compilerfehler.

Bearbeiten - Abhilfe

denke ich, sollte folgendes direkt anrufen get anstatt ausreichen, bis ein Update implementiert:

template<typename T> 
T getFromFuture(std::future<T>& fut) 
{ 
    try 
    { 
     return fut.get(); 
    } 
    catch(...) 
    { 
     fut = {}; 
     throw; 
    } 
} 
+0

nach dem Ausdrucken "" Das ist TOTAL UNERWARTET !!! "', was passiert, wenn Sie 'futInt.get()' noch einmal? – YSC

+2

g ++ 4.8.4 gibt "foo Ausnahme" und "Dies wird erwartet." –

+0

@YSC - die "foo exception" wird erneut ausgelöst (ich habe dies getestet, indem ich die Innenseite der ersten if-Anweisung direkt nach dem cout kopiert habe). – AlphaXerion

Antwort

3

ich unter Linux kompiliert mit gcc 5.2.0 und Klirren 3 .7.0 - beide Male mit 64 Bit. Ausführen des Programms führt immer in

foo exception 
This is expected. 

Es mir wie Visual 2013 sieht verarbeitet falsch diese. Siehe auch:

C++ §30.6.6/16-17

Wirft: die gespeicherte Ausnahme, wenn eine Ausnahme in dem freigegebenen Zustand gespeichert wurde.

Nachbedingung:valid() == false.

Die Nachbedingung wird nach den Würfen erwähnt und muss daher immer gehalten werden, auch wenn eine Ausnahme ausgelöst wird. Zumindest ist das meine Interpretation, obwohl ich nicht Standardis spreche.

Ich denke, Sie sollten wahrscheinlich auch mit Visual Studio 2015 versuchen und einen Fehler melden, wenn das die gleiche Handhabung zeigt.

+0

Bestätigtes Fehlverhalten in VS 2015. Danke für die Standardreferenz. – AlphaXerion

+1

apple clang7.0 mit libC++ auch gut erzogen. –

Verwandte Themen