Ice*_*Pic 6 c++ multithreading exception std-future
给出以下源代码
#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;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望,该计划将回应Valid: 0.使用g ++ 6.2.0就是这种情况.但是,使用MS VS2015版本14.0.25431.01 Update 3时,响应为Valid: 1.将异常传播到主线程后,未来的状态不会失效.这是一个错误还是我在这里遇到了未定义的行为?
我看来是个bug。
根据std::future::get文档,valid()应该false在调用后返回get。
任何共享状态都会被释放。
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);
}
Run Code Online (Sandbox Code Playgroud)
基本上,_Retreived还应该设置为trueif_Exception持有exception_ptr. 在抛出时,这个变量永远不会被设置。看来,当他们测试它时,他们没有测试就绪的未来,只测试了非就绪的未来,因为后者不会显示此错误。