Asynchronous programming#
Futures#
- template<typenameT>
classFuture# EXPERIMENTAL A std::future-like class with more functionality.
AFuture represents the results of a past or future computation. TheFuture API has two sides: a producer side and a consumer side.
The producer API allows creating aFuture and setting its result or status, possibly after running a computation function.
The consumer API allows querying aFuture’s current state, wait for it to complete, and composing futures with callbacks.
Public Functions
- inlineFutureStatestate()const#
Return theFuture’s current state.
A return value of PENDING is only indicative, as theFuture can complete concurrently. A return value of FAILURE or SUCCESS is definitive, though.
- inlineboolis_finished()const#
Whether theFuture is finished.
A false return value is only indicative, as theFuture can complete concurrently. A true return value is definitive, though.
- inlineResult<ValueType>&&MoveResult()#
Returns an rvalue to the result.
This method is potentially unsafe
The future is not the unique owner of the result, copies of a future will also point to the same result. You must make sure that no other copies of the future exist. Attempts to add callbacks after you move the result will result in undefined behavior.
- inlineexplicitoperatorFuture()const#
Future<T> is convertible to Future<>, which views only theStatus of the original.
Marking the returnedFuture Finished is not supported.
- inlineboolWait(doubleseconds)const#
Wait for theFuture to complete, or for the timeout to expire.
trueis returned if theFuture completed,falseif the timeout expired. Note afalsevalue is only indicative, as theFuture can complete concurrently.
- inlinevoidMarkFinished(Result<ValueType>res)#
Producer API: markFuture finished.
TheFuture’s result is set to
res.
- template<typenameE=ValueType,typename=typenamestd::enable_if<std::is_same<E,internal::Empty>::value>::type>
inlinevoidMarkFinished(Statuss=Status::OK())# Mark a Future<> completed with the providedStatus.
- template<typenameOnComplete,typenameCallback=WrapOnComplete<OnComplete>>
inlinevoidAddCallback(OnCompleteon_complete,CallbackOptionsopts=CallbackOptions::Defaults())const# Consumer API: Register a callback to run when this future completes.
The callback should receive the result of the future (const Result<T>&) For a void or statusy future this should be (constStatus&)
There is no guarantee to the order in which callbacks will run. In particular, callbacks added while the future is being marked complete may be executed immediately, ahead of, or even the same time as, other callbacks that have been previously added.
WARNING: callbacks may hold arbitrary references, including cyclic references. Since callbacks will only be destroyed after they are invoked, this can lead to memory leaks if aFuture is never marked finished (abandoned):
{ auto fut =Future<>::Make(); fut.AddCallback([fut]() {}); }
In this example
futfalls out of scope but is not destroyed because it holds a cyclic reference to itself through the callback.
- template<typenameCallbackFactory,typenameOnComplete=detail::result_of_t<CallbackFactory()>,typenameCallback=WrapOnComplete<OnComplete>>
inlineboolTryAddCallback(CallbackFactorycallback_factory,CallbackOptionsopts=CallbackOptions::Defaults())const# Overload of AddCallback that will return false instead of running synchronously.
This overload will guarantee the callback is never run synchronously. If the future is already finished then it will simply return false. This can be useful to avoid stack overflow in a situation where you have recursive Futures. For an example see the Loop function
Takes in a callback factory function to allow moving callbacks (the factory function will only be called if the callback can successfully be added)
Returns true if a callback was actually added and false if the callback failed to add because the future was marked complete.
- template<typenameOnSuccess,typenameOnFailure=PassthruOnFailure<OnSuccess>,typenameOnComplete=ThenOnComplete<OnSuccess,OnFailure>,typenameContinuedFuture=typenameOnComplete::ContinuedFuture>
inlineContinuedFutureThen(OnSuccesson_success,OnFailureon_failure={},CallbackOptionsoptions=CallbackOptions::Defaults())const# Consumer API: Register a continuation to run when this future completes.
The continuation will run in the same thread that called MarkFinished (whatever callback is registered with this function will run before MarkFinished returns). Avoid long-running callbacks in favor of submitting a task to an Executor and returning the future.
Two callbacks are supported:
OnSuccess, called with the result (const ValueType&) on successful completion. for an empty future this will be called with nothing ()
OnFailure, called with the error (constStatus&) on failed completion. This callback is optional and defaults to a passthru of any errors.
Then() returns aFuture whose ValueType is derived from the return type of the callbacks. If a callback returns:
void, a Future<> will be returned which will completes successfully as soon as the callback runs.
Status, a Future<> will be returned which will complete with the returnedStatus as soon as the callback runs.
V or Result<V>, aFuture<V> will be returned which will complete with the result of invoking the callback as soon as the callback runs.
Future<V>, aFuture<V> will be returned which will be marked complete when the future returned by the callback completes (and will complete with the same result).
The continuedFuture type must be the same for both callbacks.
Note that OnFailure can swallow errors, allowing continued Futures to successfully complete even if thisFuture fails.
If this future is already completed then the callback will be run immediately and the returned future may already be marked complete.
See AddCallback for general considerations when writing callbacks.
- inlineFuture(ValueTypeval)#
Implicit constructor to create a finished future from a value.
Public Static Functions
- staticinlineFutureMake()#
Producer API: instantiate a validFuture.
TheFuture’s state is initialized with PENDING. If you are creating a future with this method you must ensure that future is eventually completed (with success or failure). Creating a future, returning it, and never completing the future can lead to memory leaks (for example, see Loop).
- template<typenameOnSuccess>
structPassthruOnFailure#
- inlineFutureStatestate()const#
- template<typenameT>
staticFuture<T>DeferNotOk(Result<Future<T>>maybe_future)# If a Result<Future> holds an error instead of aFuture, construct a finishedFuture holding that error.
- template<typenameT>
Future<std::vector<Result<T>>>All(std::vector<Future<T>>futures)# Create aFuture which completes when all of
futurescomplete.The future’s result is a vector of the results of
futures. Note that this future will never be marked “failed”; failed results will be stored in the result vector alongside successful results.
- FutureAllComplete(conststd::vector<Future<>>&futures)#
Create aFuture which completes when all of
futurescomplete.The future will be marked complete if all
futurescomplete successfully. Otherwise, it will be marked failed with the status of the first failing future.
- FutureAllFinished(conststd::vector<Future<>>&futures)#
Create aFuture which completes when all of
futurescomplete.The future will finish with an ok status if all
futuresfinish with an ok status. Otherwise, it will be marked failed with the status of one of the failing futures.Unlike AllComplete thisFuture will not complete immediately when a failure occurs. It will wait until all futures have finished.

