mardi 24 novembre 2015

std::future still valid after calling get() (which throws an exception)

According to cppreference, after calling std::future::get:

valid() is false after a call to this method.

Additionally, from cplusplus.com:

Once the shared state is ready, the function unblocks and returns (or throws) releasing its shared state. This makes the future object no longer valid: this member function shall be called once at most for every future shared state.

And under Exception safety:

The function throws the exception stored in the shared state when the provider makes it ready by setting it to an exception. Note that in this case a basic guarantee is offered, with the future object being modified to no longer be a valid future (which is itself a valid state for object of this type, despite its name).

Neither description makes a distinction between a call to get which returns a value versus one that throws an exception regarding the invalidation of the future object.

However, the described behavior is not what I'm seeing with this example code:

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

The output I see is:

foo exception
This is TOTALLY UNEXPECTED!!!

I'm using Visual Studio Premium 2013, Version 12.0.30501.00 Update 2. Is this a bug with the compiler or, in fact, correct behavior in the case of an exception? I've been unable to find any bug reports concerning this, so wasn't sure if it was expected behavior.

Aucun commentaire:

Enregistrer un commentaire