7

Given the following source code

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

}

I would expect, that the program will response with Valid: 0. Using g++ 6.2.0 this is the case. However, using MS VS2015 Version 14.0.25431.01 Update 3 the response is Valid: 1. The state of the future is not invalidaded, after the exception was propagated to the main thread. Is this a bug or am i running into undefined behaviour here?

1 Answer 1

4

I appears to be a bug.

According to std::future::get documentation , valid() should return false after a call to get.

Any shared state is released. valid() is false after a call to this method.

Digging a bit into VC++ implementation of get, there is a bug there:

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

basically, _Retreived should also be set to true if _Exception holds an exception_ptr. by the time of throwing, this variable is never set. it appears that when they tested it, they didn't test for a ready future, only for non ready future, because the latter will not show this bug.

Sign up to request clarification or add additional context in comments.

2 Comments

Is there a workaround? When i remove the wait_for statement it works as expected, but in my production code i need a program flow similiar to the sample source.
@IcePic maybe use concurrency::task instead. under VC++, std::async is a thin wrapper around tasks anyway.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.