2017-03-07 66 views
5

考慮下面的源代碼的std ::期貨和異常

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

} 

我預計,該計劃將與Valid: 0響應。使用g ++ 6.2.0就是這種情況。但是,使用MS VS2015版本14.0.25431.01更新3的響應是Valid: 1。在異常傳播到主線程之後,未來的狀態不會失效。這是一個錯誤還是我在這裏遇到未定義的行爲?

回答

1

我似乎是一個錯誤。

根據std::future::get documentationvalid()在致電get後應返回false

任何共享狀態被釋放。在調用此方法後,valid()false

挖比特到VC++實現的get,這裏面就有了一個錯誤:

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

基本上_Retreived也應該如果_Exception持有exception_ptr設置爲true。在投擲時,這個變量從未設置。看起來當他們測試它時,他們沒有測試好未來, 只適用於未來的未來,因爲後者不會顯示這個bug。

+0

有沒有解決方法?當我刪除wait_for語句時,它按預期工作,但在我的生產代碼中,我需要類似於示例源的程序流。 – IcePic

+0

@IcePic也許使用'concurrency :: task'。在VC++下,'std :: async'是一個簡單的包裝任務。 –