This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++0x] Back to the <future>


This patch updates <future> to match the n3000 working paper.

The main change since the last WP is that calls to promise::set_value
/ promise::set_exception must be serialised. That term isn't properly
defined in the standard, but the intention is pretty clear.  My
interpretation of the previous spec was that concurrent calls to
promise::set_value resulted in a data race, and the second call (the
one that lost the race) could throw immediately, even while the first
call was still executing set_value.   Now the second call has to wait
until the first finishes.  This is quite a big change, but is quite
easily implemented using std::call_once to ensure calls are
serialized.  All calls that set a value in the associated state create
a std::function<Ptr<R>()> which is passed to _State::_M_set_result,
which then runs the functor with call_once, ensuring that the result
can only be set once per associated state (and any side effects of
setting that state must be done by the functor, so they only happen
once as well.)

Other changes are renaming unique_future to future, removing
future::is_ready, future::has_value and future::has_exception, but
adding future::valid, and adding some default constructors and move
operations.  That obviously broke all the tests I spent ages writing
to check is_ready/has_value etc. :-)  I haven't renamed the test
directory from unique_future to future.

In order to implement the async functions I created two new classes
derived from __future_base::_State, _Async_state and _Deferred_state,
and in doing so realised that packaged_task would be simpler if it
used a similar _Task_state type instead of using a promise.  Futures
hold a shared_ptr<_State>, so they don't know or care that it might
actually be an _Async_state or a _Task_state. The one exception is
that a future returned by async(launch::sync,...) has a "deferred
function" which must be invoked when you wait for the result, so
_State::_M_wait calls a virtual function, _M_run_deferred, which gives
a _Deferred_state a chance to invoke the function.

I haven't implemented atomic_future. I think that can be done without
shared_ptr atomic access functions, by giving atomic_future a mutex
member and locking appropriately, but I haven't analysed that properly
yet.  In any case, it shouldn't need another re-design of the base
classes and result handling.

Allocator support is included, but still commented out until
allocator_arg_t is available.

Tested x86_64/Linux.  This only affects C++0x mode so I'd like to
commit it for 4.5, fixing libstdc++/42201

Attachment: future-cl.txt
Description: Text document

Attachment: future-n3000.txt
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]