Exercise 7. std::future from scratch, part 2.

Exercise 7a. Implement .set_ready() and .set_continuation().

Open this wandbox (b, b, b, b). It contains an almost-complete implementation of my::future<T> for object types (i.e. not void or reference types).

Your task is to implement future_shared_state::set_ready() and future_shared_state::set_continuation().

set_ready needs to do the following things: set_continuation needs to do the following things: Remember that set_continuation is called from future::then, and set_ready is called from promise::set_value. So, to avoid a race between set_continuation's read and set_ready's write, both functions must deal with m_then under a mutex lock. (You should use m_mtx for this purpose.)

But you must not call m_then under the mutex lock! Why not?

Exercise 7b (optional). Now do it without data races.

Use our -DX=std::this_thread::sleep_for(1ms); trick to test your implementations. Do they really work?

Exercise 7c (optional). Now do it without running user code under a lock.

If your solution involves running m_then() while still holding the mutex lock, that's probably a problem.

Consider that even running something as trivial-looking as m_then = std::move(continuation); will call the move-constructor of unique_function<void()>, which could call the move-constructor of any T that has been captured inside the unique_function. Is this a problem? How could we solve it? (This is an open question, as far as I know.)


You're done with the seventh set of exercises! Sit back and relax, or optionally, browse the following links.