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:
m_ready=true.m_cv.notify_all() to wake up the waiting future (if any).m_then(), if it is non-empty.set_continuation needs to do the following things:
continuation() and return.m_then = continuation.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?
Use our -DX=std::this_thread::sleep_for(1ms); trick to test your implementations.
Do they really work?
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.