Skip to content

Adaptors Library

Functions to create new futures from existing functions.

This module defines functions we can use to create new futures from existing futures. Future adaptors are future types of whose values are dependent on the condition of other future objects.

Classes

Classes Description
when_all_future Proxy future class referring to a conjunction of futures from when_all.
(class)
when_any_result Result type for when_any_future objects.
(struct)
when_any_future Future object referring to the result of a disjunction of futures.
(class)

Functions

Member Functions Description
operator% Create a proxy pair with a lambda and an executor.
(function template)
make_ready_future Make a placeholder future object that is ready at construction.
(function)
make_exceptional_future Make a placeholder future object that is ready with an exception from an exception ptr.
(function template)
then Schedule a continuation function to a future.
(function template)
operator>> Operator to schedule a continuation function to a future.
(function template)
when_all Create a future object that becomes ready when the range of input futures becomes ready.
(function template)
operator&& Create a future object that becomes ready when the range of input futures becomes ready.
(function template)
when_any Create a future object that becomes ready when any of the futures in the range is ready.
(function template)
operator|| Create a future object that becomes ready when any of the futures in the range is ready.
(function template)
is_ready Check if a future is ready.
(function template)

Functions

function operator%

Defined in header <futures/adaptor/bind_executor_to_lambda.hpp>

template <executor Executor, class Function>
requires /* see requirements below */
/* see return type below */
operator%(Executor const & ex, Function && after);

Create a proxy pair with a lambda and an executor.

Parameters

  • after - A callable with the continuation
  • ex - An executor

Return value

A proxy pair to schedule execution

Description

For this operation, we needed an operator with higher precedence than operator>> Our options are: +, -, *, /, %, &, !, ~. Although + seems like an obvious choice, % is the one that leads to less conflict with other functions.

Exception Safety

Basic exception guarantee.

function make_ready_future

Defined in header <futures/adaptor/make_ready_future.hpp>

(1)
basic_future< void, future_options<> >
make_ready_future();
(2)
template <class T>
basic_future< typename std::decay_t< T >, future_options<> >
make_ready_future(T && value);
(3)
template <class T>
basic_future< T &, future_options<> >
make_ready_future(std::reference_wrapper< T > value);
  1. Make a placeholder future object that is ready at construction.
  2. Make a placeholder future object that is ready at construction.
  3. Make a placeholder future object that is ready at construction.

Parameters

  • value - The value for the new future

Return value

A future associated with the shared state that is created.

Exception Safety

Basic exception guarantee.

See Also

function make_exceptional_future

Defined in header <futures/adaptor/make_ready_future.hpp>

(1)
template <class T =void>
basic_future< T, future_options<> >
make_exceptional_future(std::exception_ptr ex);
(2)
template <class T =void, class E>
basic_future< T, future_options<> >
make_exceptional_future(E ex);
  1. Make a placeholder future object that is ready with an exception from an exception ptr.
  2. Make a placeholder future object that is ready with an exception from an exception ptr.

Parameters

  • ex - The exception for the new future

Return value

A future associated with the shared state that is created.

Exception Safety

Basic exception guarantee.

See Also

function then

Defined in header <futures/adaptor/then.hpp>

(1)
template <future_like Future, class Function>
requires /* see requirements below */
/* see return type below */
then(Future && before, Function && after);
(2)
template <executor Executor, class Function, class Future>
requires /* see requirements below */
/* see return type below */
then(Executor const & ex, Future && before, Function && after);
  1. Schedule a continuation function to a future.
  2. Schedule a continuation function to a future.

Parameters

  • after - The continuation callable
  • before - The antecedent future
  • ex - The executor

Return value

  • (1) A continuation to the before future
  • (2) A continuation to the before future

Description

This function creates a continuation that gets executed when the before future is completed. The continuation needs to be invocable with the return type of the previous future.

This function works for all kinds of futures but behavior depends on the input:

  • If the previous future is continuable, attach the function to the continuation list
  • If the previous future is not continuable (such as std::future), post to execution with deferred policy. In both cases, the result becomes a cfuture or jcfuture.

Stop tokens are also propagated:

  • If after function expects a stop token:
    • If previous future is stoppable and not-shared: return jcfuture with shared stop source
    • Otherwise: return jcfuture with new stop source
  • If after function does not expect a stop token:
    • If previous future is stoppable and not-shared: return jcfuture with shared stop source
    • Otherwise: return cfuture with no stop source

Exception Safety

Basic exception guarantee.

function operator>>

Defined in header <futures/adaptor/then.hpp>

(1)
template <future_like Future, class Function>
requires /* see requirements below */
/* see return type below */
operator>>(Future && before, Function && after);
(2)
template <class Executor, class Future, class Function, bool RValue>
requires /* see requirements below */
/* see return type below */
operator>>(
    Future && before, 
    detail::executor_and_callable_reference< Executor, Function, RValue > && after);
  1. Operator to schedule a continuation function to a future.
  2. Schedule a continuation function to a future.

Parameters

  • after - The continuation callable
  • before - The antecedent future

Return value

  • (1) A continuation to the before future
  • (2) A continuation to the before future

Description

This function creates a continuation that gets executed when the before future is completed. The continuation needs to be invocable with the return type of the previous future.

This function works for all kinds of futures but behavior depends on the input:

  • If the previous future is continuable, attach the function to the continuation list
  • If the previous future is not continuable (such as std::future), post to execution with deferred policy. In both cases, the result becomes a cfuture or jcfuture.

Stop tokens are also propagated:

  • If after function expects a stop token:
    • If previous future is stoppable and not-shared: return jcfuture with shared stop source
    • Otherwise: return jcfuture with new stop source
  • If after function does not expect a stop token:
    • If previous future is stoppable and not-shared: return jcfuture with shared stop source
    • Otherwise: return cfuture with no stop source

Exception Safety

Basic exception guarantee.

function when_all

Defined in header <futures/adaptor/when_all.hpp>

(1)
template <class InputIt>
requires /* see requirements below */
when_all_future< __see_below__ >
when_all(InputIt first, InputIt last);
(2)
template <class Range>
requires is_range_v<std::decay_t<Range>>
when_all_future< __see_below__ >
when_all(Range && r);
(3)
template <class... Futures>
requires /* see requirements below */
when_all_future< std::tuple< __see_below__ > >
when_all(Futures &&... futures);
  1. Create a future object that becomes ready when the range of input futures becomes ready.
  2. Create a future object that becomes ready when the range of input futures becomes ready.
  3. Create a future object that becomes ready when the range of input futures becomes ready.

Parameters

  • first, last - Range of futures
  • futures - Instances of future objects
  • r - Range of futures

Return value

Future object of type when_all_future

Description

(1) This function does not participate in overload resolution unless InputIt's value type (i.e., typename std::iter_value_t) is a std::future or std::shared_future.

This overload uses a small vector for avoid further allocations for such a simple operation.

(2) This function does not participate in overload resolution unless the range is_future_like trait.

(3) This function does not participate in overload resolution unless every argument is either a (possibly cv-qualified) shared_future or a cv-unqualified future, as defined by the is_future_like trait.

Exception Safety

Basic exception guarantee.

function operator&&

Defined in header <futures/adaptor/when_all.hpp>

template <class T1, class T2>
requires /* see requirements below */
/* see return type below */
operator&&(T1 && lhs, T2 && rhs);

Create a future object that becomes ready when the range of input futures becomes ready.

Parameters

  • lhs, rhs - Future objects or callables

Return value

when_all_future object that concatenates all futures

Description

Operator&& works for futures and functions (which are converted to futures with the default executor) If the future is a when_all_future itself, then it gets merged instead of becoming a child future of another when_all_future.

When the user asks for f1 && f2 && f3, we want that to return a single future that waits for <f1,f2,f3> rather than a future that wait for two futures <f1,<f2,f3>>.

This emulates the usual behavior we expect from other types with operator&&.

Note that this default behaviour is different from when_all(...), which doesn't merge the when_all_future objects by default, because they are variadic functions and this intention can be controlled explicitly:

  • when_all(f1,f2,f3) -> <f1,f2,f3>
  • when_all(f1,when_all(f2,f3)) -> <f1,<f2,f3>>

Exception Safety

Basic exception guarantee.

function when_any

Defined in header <futures/adaptor/when_any.hpp>

(1)
template <class InputIt>
requires /* see requirements below */
when_any_future< __see_below__ >
when_any(InputIt first, InputIt last);
(2)
template <std::ranges::range Range>
when_any_future< __see_below__ >
when_any(Range && r);
(3)
template <class... Futures>
requires /* see requirements below */
when_any_future< std::tuple< __see_below__ > >
when_any(Futures &&... futures);
  1. Create a future object that becomes ready when any of the futures in the range is ready.
  2. Create a future object that becomes ready when any of the futures in the range is ready.
  3. Create a future object that becomes ready when any of the futures in the range is ready.

Parameters

  • first, last - Range of futures
  • futures - A sequence of future objects
  • r - Range of futures

Return value

Description

(2) This function does not participate in overload resolution unless every argument is future-like.

(3) This function does not participate in overload resolution unless every argument is either a (possibly cv-qualified) std::shared_future or a cv-unqualified std::future.

Exception Safety

Basic exception guarantee.

function operator||

Defined in header <futures/adaptor/when_any.hpp>

template <class T1, class T2>
requires /* see requirements below */
/* see return type below */
operator||(T1 && lhs, T2 && rhs);

Create a future object that becomes ready when any of the futures in the range is ready.

Parameters

  • lhs, rhs - Future objects

Return value

A when_any_future holding all future types

Description

ready operator|| works for futures and functions (which are converted to futures with the default executor) If the future is a when_any_future itself, then it gets merged instead of becoming a child future of another when_any_future.

When the user asks for f1 || f2 || f3, we want that to return a single future that waits for <f1 || f2 || f3> rather than a future that wait for two futures <f1 || <f2 || f3>>.

This emulates the usual behavior we expect from other types with operator||.

Note that this default behaviour is different from `when_any(...), which doesn't merge the when_any_future objects by default, because they are variadic functions and this intention can be controlled explicitly:

  • when_any(f1,f2,f3) -> <f1 || f2 || f3>
  • when_any(f1,when_any(f2,f3)) -> <f1 || <f2 || f3>>

Exception Safety

Basic exception guarantee.

function is_ready

Defined in header <futures/is_ready.hpp>

template <future_like Future>
bool
is_ready(Future && f);

Check if a future is ready.

Description

Although basic_future has its more efficient is_ready function, this free function allows us to query other futures that don't implement is_ready, such as std::future.

Exception Safety

Basic exception guarantee.


Updated on 2023-01-04