Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Valid futures vs Default constructed futures

I am studying futures in my concurrent programming class. My professor has stated this in her slides:

"Valid" futures are future objects associated to a 
shared state, and are constructed by calling one of the following functions:

async
promise::get_future
packaged_task::get_future

future objects are only useful when they are valid. Default-constructed future objects are not valid (unless move-assigned a valid future).

I can't understand the meaning of the above, especially the "unless move-assigned a valid future" part. Could someone please explain this in simple terms, and perhaps show some example code as well?

like image 442
Flame of udun Avatar asked Oct 31 '16 14:10

Flame of udun


1 Answers

As stated in the std::future constructor:

Default-constructed future objects are not valid

This just means calling the default constructor for the object, something like:

std::future<int> f;

This will call constructor #1 which states:

Default constructor. Constructs a std::future with no shared state. After construction, valid() == false.

As for the other part:

(unless move-assigned a valid future)

What is meant here is that the move constructor (future( future&& other ) #2) will be called which states:

Move constructor. Constructs a std::future with the shared state of other using move semantics. After construction, other.valid() == false.

Basically, the state of other in this constructor is moved to this. That means if other.valid() == true then after the move constructor has returned other.valid() will be false and this.valid() will be true. If other.valid() was false to begin with then both will end up false.

std::future<int> fut; // fut.valid() == false, default constructor

std::future<int> valid_fut = std::async(std::launch::async, [](){ return 42; }); // obtain a valid std::future..
// valid_fut.valid() == true here

//now move valid_fut into new_fut
std::future<int> new_fut(std::move(valid_fut));
// new_fut.valid() == true
// valid_fut.valid() == false

To summarize:

  • Calling the default constructor for an std::future will result in valid() == false. Always.

  • Calling the move constructor for an std::future will result in valid() == true only if other.valid() was true before moving from it. False otherwise.

like image 104
Hatted Rooster Avatar answered Oct 26 '22 22:10

Hatted Rooster