Guide
std::execution Overview
This page provides an overview of the components in std::execution. The documentation on this page doesn’t represent all details of the specification. However, it should capture enough details to be a suitable resource to determine how the various components are used.
For each of the components a summary view is provided. To get more details expand the respective section.
Terms
This section defines a few terms used throughout the description on this page. The terms aren’t taken from the specification and are, thus, somewhat informal.
completion signal
When an asynchronous operation completes it signals its completion by calling a completion function on a receiver:
-
std::execution::set_value(receiver, args…)is called when an operation completes successfully. A call to this completion function is referred to as value completion signal. -
std::execution::set_error(receiver, error)is called when an operation fails to deliver its success results. A call to this completion function is referred to as error completion signal. -
std::execution::set_stopped()is called when an operation was cancelled. A call to this completion function is referred to as cancellation completion signal. -
Collectively the value, error, and cancellation completion signals are referred to as completion signal. Note that any `start`ed asynchronous operation triggers exactly one completion signal.
environment
The term enviroment refers to the bag of properties associated with an object by the call std::execution::get_env(object). By default the environment for objects is empty (std::execution::env<>). In particular, environments associated with receiver`s are used to provide access to properties like the stop token, scheduler, or allocator associated with the `receiver. The various properties associated with an object are accessed via queries.
Concepts
This section lists the concepts from std::execution.
inlinable_receiver<Rcvr, Child>
The concecpt inlinable_receiver<Rcvr, Child> detects if a receiver of type Rcvr can be obtained from a Child reference using Rcvr::make_receiver_for(child). It is unspecified if any of the standard library receivers is a inlinable_receiver.
operation_state<State>
Operation states represent asynchronous operations ready to be `start`ed or executing. Operation state objects are normally neither movable nor copyable. Once `start`ed the object needs to be kept alive until a completion signal is received. Users don’t interact with operation states explicitly except when implementing new sender algorithms.
Required members for State:
-
The type
operation_state_conceptis an alias foroperation_state_tagor a type derived thereof. -
state.start() & noexcept
Example
This example shows a simple operation state object which immediately completes successfully without any values (as () would do). Normally start() initiates an asynchronous operation completing at some point later.
template <std::execution::receiver Receiver>
struct example_state
{
using operation_state_concept = std::execution::operation_state_tag;
std::remove_cvref_t<Receiver> receiver;
auto start() & noexcept {
std::execution::set_value(std::move(this->receiver));
}
};
static_assert(std::execution::operation_state<example_state<SomeReceiver>>);
receiver<Receiver>
Receivers are used to receive completion signals: when an asynchronous operation completes the corresponding completion signal is called with the appropriate arguments. In addition receivers provide access to the environment for the operation via the get_env method. Users don’t interact with receivers explicitly except when implementing new sender algorithms.
Required members for Receiver:
-
The type
receiver_conceptis an alias forreceiver_tagor a type derived thereof`. -
Rvalues of type
Receiverare movable. -
Lvalues of type
Receiverare copyable. -
std::execution::get_env(receiver)returns an object. By default this operation returnsstd::execution::env<>.
Typical members for Receiver:
-
get_env() const noexcept -
set_value(args…) && noexcept → void -
set_error(error) && noexcept → void -
set_stopped() && noexcept → void
Example
The example receiver prints the name of each the received completion signal before forwarding it to a receiver. It forwards the request for an environment (get_env) to the nested receiver. This example is resembling a receiver as it would be used by a sender injecting logging of received signals.
template <std::execution::receiver NestedReceiver>
struct example_receiver
{
using receiver_concept = std::execution::receiver_tag;
std::remove_cvref_t<NestedReceiver> nested;
auto get_env() const noexcept {
return std::execution::get_env(this->nested);
}
template <typename… A>
auto set_value(A&&… a) && noexcept -> void {
std::cout << “set_value\n”;
std::execution::set_value(std::move(this->nested), std::forward<A>(a)…);
}
template <typename E>
auto set_error(E&& e) && noexcept -> void {
std::cout << “set_error\n”;
std::execution::set_error(std::move(this->nested), std::forward<E>(e));
}
auto set_stopped() && noexcept -> void {
std::cout << “set_stopped\n”;
std::execution::set_stopped(std::move(this->nested));
}
};
static_assert(std::execution::receiver<example_receiver<SomeReceiver>>);
receiver_of<Receiver, Completions>
The concept receiver_of<Receiver, Completions> tests whether std::execution::receiver<_Receiver_> is true and if an object of type Receiver can be invoked with each of the completion signals in Completions.
Example
The example defines a simple receiver and tests whether it models receiver_of with different completion signals in Completions (note that not all cases are true).
struct example_receiver
{
using receiver_concept = std::execution::receiver_tag;
auto set_value(int) && noexcept ->void {}
auto set_stopped() && noexcept ->void {}
};
// matching the exact signals models receiver_of:
static_assert(std::execution::receiver_of<example_receiver,
std::execution::completion_signals<
std::execution::set_value_t(int),
std::execution::set_stopped_t()
>);
// providing a superset of signal models models receiver_of:
static_assert(std::execution::receiver_of<example_receiver,
std::execution::completion_signals<
std::execution::set_value_t(int)
>);
// providing only a subset of signals doesn’t model receiver_of:
static_assert(not std::execution::receiver_of<example_receiver,
std::execution::completion_signals<
std::execution::set_value_t(),
std::execution::set_value_t(int)
>);
scheduler<Scheduler>
Schedulers are used to specify the execution context where the asynchronous work is to be executed. A scheduler is a lightweight handle providing a schedule operation yielding a sender with a value completion signal without parameters. The completion is on the respective execution context.
Requirements for Scheduler:
-
The type
Scheduler::scheduler_conceptis an alias forscheduler_tagor a type derived thereof. -
schedule(scheduler) → sender -
The value completion scheduler of the
sender’s environment is thescheduler:scheduler == std::execution::get_completion_schedulerstd::execution::set_value_t( std::execution::get_env(std::execution::schedule(scheduler)) )
-
std::equality_comparable<_Scheduler_> -
std::copy_constructible<_Scheduler_>
sender<Sender>
Senders represent asynchronous work. They may get composed from multiple senders to model a workflow. Senders can’t be run directly. Instead, they are passed to a sender consumer which connect`s the sender to a `receiver to produce an operation_state which may get started. When using senders to represent work the inner workings shouldn’t matter. They do become relevant when creating sender algorithms.
Requirements for Sender:
-
The type
Sender::sender_conceptis an alias forsender_tagor a type derived thereof orSenderis a suitable awaitable. -
std::execution::get_env(sender)is valid. By default this operation returnsstd::execution::env<>. -
Rvalues of type
Sendercan be moved. -
Lvalues of type
Sendercan be copied.
Typical members for Sender:
-
get_env() const noexcept -
get_completion_signatures(env) const noexcept → std::execution::completion_signatures<…> -
Sender::completion_signaturesis a type alias forstd::execution::completion_signatures<…>(if there is noget_completion_signaturesmember). -
connect(sender, receiver) → operation_state
Example
The example shows a sender implementing an operation similar to just(_value).
struct example_sender
{
template <std::execution::receiver Receiver>
struct state
{
using operation_state_concept = std::execution::operation_state_tag;
std::remove_cvref_t<Receiver> receiver;
int value;
auto start() & noexcept {
std::execution::set_value(
std::move(this->receiver),
this->value
);
}
};
using sender_concept = std::execution::sender_tag;
using completion_signatures = std::execution::completion_signatures<
std::execution::set_value_t(int)
>;
int value{};
template <std::execution::receiver Receiver>
auto connect(Receiver&& receiver) const -> state<Receiver> {
return { std::forward<Receiver>(receiver), this->value };
}
};
static_assert(std::execution::sender<example_sender>);
sender_in<Sender, Env = std::execution::env<>>
The concept sender_in<Sender, Env> tests whether Sender is a sender, Env is a destructible type, and std::execution::get_completion_signatures<_Sender_, Env>() yields a specialization of std::execution::completion_signatures.
sender-to<Sender, Receiver>
The concept sender-to<Sender, Receiver> tests if std::execution::sender_in<_Sender_, std::execution::env_of_t<_Receiver_>> is true, and if Receiver can receive all completion signals which can be sent by Sender, and if Sender can be connect`ed to `Receiver.
To determine if Receiver can receive all completion signals from Sender it checks that for each Signature in std::execution::get_completion_signals(sender, std::declval<std::execution::env_of_t<_Receiver_>>()) the test std::execution::receiver_of<_Receiver_, Signature> yields true. To determine if Sender can be connect`ed to `Receiver the concept checks if connect(std::declval<_Sender_>(), std::declval<_Receiver_>) is a valid expression.
sends_stopped<Sender, Env = std::execution::env<>>
The concept sends_stopped<Sender, Env> determines if Sender may send a stopped completion signal. To do so, the concepts determines if std::execution::get_completion_signals(sender, env) contains the signatures std::execution::set_stopped_t().
stoppable_token<Token>
A stoppable_token<Token>, e.g., obtained via std::execution::get_stop_token(env) is used to support cancellation of asynchronous operations. Using token.stop_requested() an active operation can poll whether it was requested to cancel. An inactive operation waiting for a notification can use an object of a specialization of the template Token::callback_type to get notified when cancellation is requested.
Required members for Token:
-
Token::callback_type<Callback>can be specialized with astd::callable<Callback>type. -
token.stop_requested() const noexcept → bool -
token.stop_possible() const noexcept → bool -
std::copyable<Token> -
std::equality_comparable<Token> -
std::swappable<Token>
Example: concept use
static_assert(std::execution::unstoppable_token<std::execution::never_stop_token>);
static_assert(std::execution::unstoppable_token<std::execution::stop_token>);
static_assert(std::execution::unstoppable_token<std::execution::inline_stop_token>);
Example: polling
This example shows a sketch of using a stoppable_token<Token> to cancel an active operation. The computation in this example is represented as sleep_for.
void compute(std::stoppable_token auto token)
{
using namespace std::chrono::literals;
while (not token.stop_requested()) {
std::this_thread::sleep_for(1s);
}
}
Example: inactive
This example shows how an operation_state can use the callback_type together with a token to get notified when cancellation is requested.
template <std::execution::receiver Receiver>
struct example_state
{
struct on_cancel
{
example_state& state;
auto operator()() const noexcept {
this->state.stop();
}
};
using operation_state_concept = std::execution::operation_state_tag;
using env = std::execution::env_of_t<Receiver>;
using token = std::execution::stop_callback_of_t<env>;
using callback = std::execution::stop_callback_of_t<token, on_cancel>;
std::remove_cvref_t<Receiver> receiver;
std::optional<callback> cancel{};
std::atomic<std::size_t> outstanding{};
auto start() & noexcept {
this->outstanding += 2u;
this->cancel.emplace(
std::execution::get_stop_token(this->receiver),
on_cancel{*this}
);
if (this->outstanding != 2u)
std::execution::set_stopped(std::move(this->receiver));
else {
register_work(this);
if (this->outstanding == 0u)
std::execution::set_value(std::move(this->receiver));
}
}
auto stop() {
unregister_work(this);
if (--this->outstanding == 0u)
std::execution::set_stopped(std::move(this->receiver));
}
auto complete() {
if (this->outstanding == 2u) {
this->cancel.reset();
std::execution::set_value(std::move(this->receiver));
}
}
};
unstoppable_token<Token>
The concept unstoppable_token<Token> is modeled by a Token if stoppable_token<Token> is true and it can statically be determined that both token.stop_requested() and token.stop_possible() are constexpr epxressions yielding false. This concept is used to avoid extra work when using stop tokens which will never indicate that cancellations are requested.
Example
The concept yields true for the std::execution::never_stop_token:
static_assert(std::execution::unstoppable_token<std::execution::never_stop_token>);
static_assert(not std::execution::unstoppable_token<std::execution::stop_token>);
static_assert(not std::execution::unstoppable_token<std::execution::inline_stop_token>);
Queries
The queries are used to obtain properties associated with an object.
Example defining a query on an environment
This example shows how to define an environment class which provides a get_allocator query. The objects stores a std::pmr::memory_resource* and returns a correspondingly initialized std::pmr::polymorphic_allocator<>.
struct alloc_env {
std::pmr::memory_resource res{std::pmr::new_delete_resource()};
auto query(get_allocator_t const&) const noexcept {
return std::pmr::polymorphic_allocator<>(this->res);
}
};
forwarding_query(query) -> bool
Default: false
The expression forwarding_query(query) is a constexpr query used to determine if the query query should be forwarded when wrapping an environment. The expression is required to be a core constant expression if query is a core constant expression.
The result of the expression is determined as follows:
-
The result is the value of the expression
query.query(forwarding_query)if this expression is valid andnoexcept. -
The result is
trueif the type ofqueryispublic`ly derived from `forwarding_query. -
Otherwise the result is
false.
Example
When defining a custom query custom it is desirable to allow the query getting forwarded. It is necessary to explicit define the result of forwarding_query(custom). The result can be defined by providing a corresponding query member function. When using this approach the function isn’t allowed to throw, needs to return bool, and needs to be a core constant expression:
struct custom_t {
// ...
constexpr bool query(forwarding_query_t const&) const noexcept {
return true;
}
};
inline constexpr custom_t custom{};
Alternatively, the query can be defined as forwarding by deriving publicly from forwarding_query_t:
struct custom_t: forwarding_query_t {
// ...
};
get_await_completion_adaptor(queryable) -> awaiter
If the expression get_await_completion_adaptor(queryable) is valid it yields an awaiter depending on the queryable. This query is used while getting an awaiter from a sender.
get_env(queryable) -> env
Default: env<>
The expression get_env(queryable) is used to get the environment env associated with queryable. To provide a non-default environment for a queryable a get_env member needs to be defined. If queryable doesn’t provide the get_env query an object of type env<> is returned. The value of the expression is
-
the result of
as_const(queryable).get_env()if this expression is valid andnoexcept.Example
The example defines an environment class
envwhich stores a pointer to the relevant data and is returned as the environment for the typequeryable:struct data { /*...*/ }; struct env { data* d; /* ... */ }; struct queryable { data* d; // ... env get_env() const noexcept { return { this->d }; } };Note that the
get_envmember is bothconstandnoexcept.
get_allocator(env) -> allocator
Default: none
The expression get_allocator(env) returns an allocator for any memory allocations in the respective context. If env doesn’t support this query any attempt to access it will result in a compilation error. The value of the expression get_allocator(env) is the result of as_const(env).query(get_allocator) if
-
the expression is valid;
-
the expression is
noexcept; -
the result of the expression satisfies
simple-allocator.
Otherwise the expression is ill-formed.
Example
This example shows how to define an environment class which provides a get_allocator query. The objects stores a std::pmr::memory_resource* and returns a correspondingly initialized std::pmr::polymorphic_allocator<>.
struct alloc_env {
std::pmr::memory_resource res{std::pmr::new_delete_resource()};
auto query(get_allocator_t const&) const noexcept {
return std::pmr::polymorphic_allocator<>(this->res);
}
};
get_completion_domain<Tag>(attrs) -> domain
Default: none
The expression get_completion_domain<Tag>(attrs) yields the completion domain for the completion signal Tag associated with the sender attrs. This query can be used to determine the domain a sender sender completes on for a given completion signal Tag by using get_completion_domain<Tag>(get_env(sender), ev…). The value of the expression is
Otherwise the expression is invalid.
get_completion_scheduler<Tag>(env) -> scheduler
Default: none
The expression get_completion_scheduler<Tag>(env) yields the completion scheduler for the completion signal Tag associated with env. This query can be used to determine the scheduler a sender sender completes on for a given completion signal Tag by using get_completion_scheduler<Tag>(get_env(sender)). The value of the expression is equivalent to as_const(env).query(get_completion_scheduler<Tag>) if
-
Tagis one of the typesset_value_t,set_error_t, orset_stopped_t; -
this expression is valid;
-
this expression is
noexcept; -
the expression’s type satisfies
scheduler.
Otherwise the expression is invalid.
get_completion_signatures(sender, env)
The expression get_completion_signatures(sender, env) returns an object whose type is a specialization of completion_signatures defining the possible completion signatures of sender when connected to a receiver whose <a href=‘#environment'>environment get_env(receiver) is env. A sender can define the result of this query either by defining a member function get_completion_signatures or using a type alias completion_signatures.
To determine the result the sender is first transformed using transform_sender(domain, sender, env) to get new-sender with type New-Sender-Type. With that the result type is
-
the type of
new-sender.get_completion_signatures(env)if this expression is valid; -
the type
remove_cvref_t<New-Sender-Type>::completion_signaturesif this type exists; -
completion_signatures<set_value_t(T), set_error_t(exception_ptr), set_stopped_t()>ifNew-Sender-Typeis an awaitable type which would yield an object of typeTwhen it is `co_await`ed; -
invalid otherwise.
Example
Even when a sender doesn’t need to compute the completion signatures based on an environment it is necessary to provide get_completion_signatures member function, e.g.:
struct sender {
using sender_concept = std::execution::sender_tag;
template <typename...>
static consteval void get_completion_signatures() {
return std::completion_signatures<
std::execution::set_value_t(int),
std::execution::set_error_t(std::error_code),
std::execution::set_stopped()
>{};
}
// ...
};
get_delegation_scheduler(env) -> scheduler
The expression get_delegation_scheduler(env) yields the scheduler associated with env which is used for forward progress delegation. The value of the expression is equivalent to as_const(env).query(get_delegation_scheduler) → scheduler if
-
this expression is valid;
-
this expression is
noexcept; -
the expression’s type satisfies
scheduler.
Otherwise the expression is invalid.
get_domain(env) -> domain
The expression get_domain(env) yields the domain associated with env. The value of the expression is equivalent to return D() where D is the type of the expression
-
auto(as_const(env).query(get_domain))if this expression is valid; -
otherwise,
get_completion_domain<set_value_t>(get_scheduler(env), HIDE-SCHED(env))if this expression is valid; -
default_domain()(exceptenvis evaluated).
Otherwise the expression is invalid.
get_forward_progress_guarantee(scheduler) -> forward_progress_guarantee
The expression get_forward_progress_guarantee(scheduler) yields the forward progress guarantee of the scheduler’s execution agent. The value of the expression is equivalent to as_const(env).query(get_forward_progress_guarantee) if
-
this expression is valid;
-
this expression is
noexcept;Otherwise the expression is invalid.
get_scheduler(env) -> scheduler
The expression get_scheduler(env) yields the scheduler associated with env. The value of the expression is equivalent to as_const(env).query(get_scheduler) if
-
this expression is valid;
-
this expression is
noexcept;Otherwise the expression is invalid.
get_start_scheduler(env) -> scheduler
The expression get_start_scheduler(env) yields the scheduler associated with env. The value of the expression is equivalent to as_const(env).query(get_scheduler) if
-
this expression is valid;
-
this expression is
noexcept;Otherwise the expression is invalid.
If the expression get_start_scheduler(get_env(rcvr)) is well-formed it should yield the scheduler the operation state resulting from connect(sndr, rcvr) gets `start`ed on.
get_stop_token(env) -> stoppable_token
The expression get_stop_token(env) yields the stop token associated with env. The value is the result of the expression as_const(env).query(get_stop_token) if
-
the expression is valid;
-
the expression is
noexcept; -
the expression satisfies
stoppable_token.
Otherwise the value is never_stop_token{}.
Customization Point Objects
connect(sender, receiver) -> operation_state
The expression connect(sender, receiver) combines sender and receiver into an operation state state. When this state gets started using start(state) the operation represented by sender gets started and reports its completion to receiver or an object copied or moved from receiver. While the operation state state isn’t started it can be destroyed but once it got started it needs to stay valid until one of the completion signals is called on receiver.
set_error(receiver, error) noexcept -> void
The expression set_error(receiver, error) invokes the set_error completion signal on receiver with the argument error, i.e., it invokes receiver.set_error(error).
set_stopped(receiver) noexcept -> void
The expression set_stopped(receiver) invokes the set_stopped completion signal on receiver, i.e., it invokes receiver.set_stopped().
set_value(receiver, value...) noexcept -> void
The expression set_value(receiver, value…) invokes the set_value completion signal on receiver with the argument(s) value…, i.e., it invokes receiver.set_value(value…).
start(state) noexcept -> void
The expression start(state) starts the execution of the operation_state object state. Once this expression started executing the object state is required to stay valid at least until one of the completion signals of state’s receiver is invoked. Once started exactly one of the completion signals is eventually called.
Senders
Sender Factories
Sender factories create a sender which forms the start of a graph of lazy work items.
just(value...) -> sender-of<set_value_t(Value...)>
The expression just(value…) creates a sender which sends value… on the set_value (success) channel when started (note that value… can be empty).
Completions
-
set_value_t(decltype(value)…)
just_error(error) -> sender-of<set_error_t(Error)>
The expression just_error(error) creates a sender which sends error on the set_error (failure) channel when started.
Completions
-
set_error_t(decltype(error))
just_stopped() -> sender-of<set_stopped_t()>
The expression just_stopped() creates a sender which sends a completion on the set_stopped (cancellation) channel when started.
Completions
-
set_stopped_t()
read_env(query) -> sender-of<set_value_t(query-result)>
The expression read_env(query) creates a sender which sends the result of querying query the environment of the receiver it gets connected to on the set_value channel when started. Put differently, it calls set_value(move(receiver), query(get_env(receiver))). For example, in a coroutine it may be useful to extra the stop token associated with the coroutine which can be done using read_env:
auto token = co_await read_env(get_stop_token);
Completions
-
set_value_t(decltype(query(get_env(receiver))))
schedule(scheduler) -> sender-of<set_value_t()>
The expression schedule(scheduler) creates a sender which upon success completes on the set_value channel without any arguments running on the execution context associated with scheduler. Depending on the scheduler it is possible that the sender can complete with an error if the scheduling fails or using set_stopped() if the operation gets cancelled before it is successful.
Completions
-
set_value_t()upon success -
set_error_t(Error)upon failure ifschedulermay fail -
set_stopped_t()upon cancellation ifschedulersupports cancellation
Sender Adaptors
The sender adaptors take one or more senders and adapt their respective behavior to complete with a corresponding result. The description uses the informal function completions-of(sender) to represent the completion signatures which sender produces. Also, completion signatures are combined using +: the result is the deduplicated set of the combined completion signatures.
affine(sender) -> sender-of<completions-of(sender)>
The expression affine(sender) creates a sender which completes on the same scheduler it was started on, even if sender changes the scheduler. The scheduler to resume on is determined using get_start_scheduler(get_env(rcvr)) where rcvr is the receiver the sender is connect`ed to. The scheduler `sched returned from get_start_scheduler(get_env(rcvr)) has to be infallible, i.e., the completion signtures of scheduler(sched) only contain set_value_t().
The primary use of affine is implementing scheduler affinity for task.
associate(sndr, token) -> sender
bulk(sndr, policy, shape, fun) -> sender
bulk_chunked(sndr, policy, shape, fun) -> sender
bulk_unchunked(sndr, policy, shape, fun) -> sender
continues_on(sender, scheduler) -> sender-of<completions-of(sender) + completions-of(schedule(scheduler))>
The expression continues_on(sender, scheduler) creates a sender cs which starts sender when started. The results from sender are stored. Once that is cs creates a sender using schedule(scheduler) and completes itself on the execution once that sender completes.
Completions
-
completions-of(sender) -
completions-of(schedule(scheduler))
into_variant(sender) -> sender-of<set_value_t(std::variant<Tuple...>)>
The expression into_variant(sender) creates a sender which transforms the results of possibly multiple set_value completions of sender into one set_value completion representing the different upstream results as different options of a variant<Tuple…> where each Tuple is a tuple of values initialized with the respective arguments passed to set_value. The order of options in the variant isn’t specified.
let_error(upstream, fun) -> sender
The expression let_error(upstream, fun) yields a sender sndr which uses an error completion (set_error) of upstream as an argument to invoke fun which has to return another sender inner-sndr and the completion of inner-sndr becomes the completion of sndr. If this invocation results in an exception sndr completes with an error completion the result of std::current_exception. If upstream completes successfully (set_value) or with a cancellation (set_stopped) this completion becomes the completion of sndr.
let_stopped(upstream, fun) -> sender
The expression let_stopped(upstream, fun) yields a sender sndr which uses a cancellation completion (set_stopped) of upstream to invoke fun which has to return another sender inner-sndr and the completion of inner-sndr becomes the completion of sndr. If this invocation results in an exception sndr completes with an error completion the result of std::current_exception. If upstream completes successfully (set_value) or with an error (set_error) this completion becomes the completion of sndr.
let_value(upstream, fun) -> sender
The expression let_value(upstream, fun) yields a sender sndr which uses a successful completion (set_value) of upstream as arguments to invoke fun which has to return another sender inner-sndr and the completion of inner-sndr becomes the completion of sndr. If this invocation results in an exception sndr completes with an error completion the result of std::current_exception. If upstream completes with a cancellation (set_stopped) or with an error (set_error) this completion becomes the completion of sndr.
on(_sched_, _sndr_), on(_sndr, _sched_, _closure_)
The on algorithm is a pipeable sender adaptor. Let on-sender be
-
sndrwhen the formon(sched, sndr)is used; -
closure(sndr)when the formon(sndr, sched, closure)is used.
The sender on-sndr is started on sched’s execution context. The `on algorithm completes on the original scheduler (obtained using get_start_scheduler) with the result of the on-sndr.
schedule_from(sender) -> sender
The expression schedule_from(sender) yields a sender which behaves likes sender. The purpose of the schedule_from is to allow schedulers to customize the way how to transition off the execution context.
spawn_future(sndr, token) -> sender
split
starts_on(scheduler, sender) -> sender
The expression starts_on(scheduler, sender) yields a sender which starts sender on the scheduler’s context, i.e., it starts `schedule(scheduler) and then starts sender where the scheduler’s sender completes.
stopped_as_error(sndr)
stopped_as_optional(sndr)
then(upstream, fun) -> sender
The expression then(upstream, fun) yields a sender sndr which on successful completion of upstream (set_value) calls fun with the arguments passed to set_value and yields the function return as its own result. If the function throws or upstream completes with an error (set_error) the exception or the error becomes sndr’s result. If `upstream completes with a cancellation (set_stopped).
unstoppable(sender) -> sender
The expression unstoppable(sender) yields a sender which passes its receiver’s environment to sender except that the get_stop_token query return never_stop_token: the resulting sender behaves like sender except that it is unstoppable.
upon_error(upstream, fun) -> sender
The expression upon_error(upstream, fun) yields a sender sndr which passes an error completion (set_error) of upstream to fun and uses this result of this function invocation for its own successful (set_value) completion. If the function invocation throws std::current_exception() becomes sndr’s error (`set_error) completion. The success (set_value) and cancellation (set_stopped) completions of upstream are forwarded.
upon_stopped(upstream, fun) -> sender
The expression upon_stopped(upstream, fun) yields a sender sndr which turns a cancellation completion (set_stopped) result of upstream to fun and uses this result of this function invocation for its own successful (set_value) completion. If the function invocation throws std::current_exception() becomes sndr’s error (`set_error) completion. The success (set_value) and error (set_error) completions of upstream are forwarded.
when_all(sender...) -> sender
The expression when_all(sender…) yields a sender sndr which completes successfully (set_value) when all nested senders sender… completed successfully using the results of the nested senders in order. If any of the senders completes with an error (set_error) or a cancellation (set_stopped) the first such completion becomes the completion of sndr once all nested senders completed. A stop is requested for the stop source(s) whose token was passed to the nested senders.
when_all_with_variant(sender...) -> sender
write_env(sender, env) -> sender
The expression write_env(sender, env) creates a sender which passes a receiver to sender which combines the environment env with the environment from the receiver’s environment. The queries from env take precedence over those from the receiver’s environment.
Sender Consumers
sync_wait(sender) -> std::optional<std::tuple<T...>>
sync_wait_with_variant(sender) -> std::optional<std::variant<std::tuple<T...>...>>
spawn(sndr, token) -> void
Helpers
adapt-for-await-completion(s)
The expression is equivalent to get_await_completion_adaptor(get_env(s))(s) except that s is evaluated only once.
as_awaitable(expr, promise)
The expression as_awaitable(expr, promise) tries to create an awaitable from expr and promise. It tries the following transformations:
-
expr.as_awaitable(promise)if this expression is well-formed; otherwise -
adapt-for-await-completion(transform_sender(expr, get_env(promise)))if this expression is well-formed; otherwise -
exprifGET-AWAITER(expr)is an awaiter forpromise; otherwise. -
sender-awaitable{adapt-for-await-completion(transform_sender(expr, get_env(promise))), promise}if this expression is well-formed; otherwise -
expr
-
with_awaitable_sender -
apply_sender
completion_signatures<Sig...>
The template specialization completion_signatures<Sig…> is a list of completion signatures used to declare and compute the result types of senders.
It has two exposition-only members template:
-
count-of(tag)providing a constant expression with the count oftagcompletions. -
for-each(fun)invokingfunwith a pointer to each of the completion signaturesSig…. The function is used to verify the completion signature types.
-
completion_signatures_t -
connect_result_t -
default_domain
env<Ev...>
The expression env(ev…) creates an environment by combining the environments ev…. If multiple of the environments support an identical query, the first one from the first environment is used.
-
env_of_t
error_types_of_t<Sndr, Env = env<>, Variant = variant-or-empty>
The template specialization error_types_of_t<sndr, Env, Variant> gets Sndr error completion signatures when using the environment Env. The results is represented as a Variant<E… where E… is the list of argument types to the completion signatures.
-
fwd_env -
operation_state_tag
prop<Query, Value>
The expression prop(query, value) create an object which can be queried for query query which results in value.
-
receiver_tag
run_loop
The class run_loop provides a scheduler to execute work on. It is used to implement sync_wait(sndr). The public methods on an object loop of type run_loop are:
-
loop.get_scheduler()to get a scheduler scheduling work onloop. -
loop.finish()to requestloopto exit processing work items. Note thatrun_loopdoesn’t maintain a stop source, i.e., when this operation is invoked the work doesn’t get cancelled.
-
scheduler_tag -
schedule_result_t -
sender_adaptor_closure -
sender_tag
bool sends_stopped<Sndr, Env = env<>>
The Boolean variable sends_stopped<Sndr, Env> is true if the completion signatures of Sndr when using the environment Env contain a cancellation signature (set_stopped_t()).
-
stop_token_of_t
tag_of_t<Sndr>
-
if
auto&&[tag, data, children…] = sndr;is well-formed the typedecltype(auto(tag)); -
otherwise ill-formed.
-
transform_sender -
transform_completion_signatures -
transform_completion_signatures_of
value_types_of_t<Sndr, Env = env<>, Tuple = decayed-tuple, Variant = variant-or-empty>
The template specialization value_types_of_t<Sndr, Env, Tuple, Variant> gets Sndr success completion signatures when using the environment Env. The resulting type is a Variant of Tuple elements where each Tuple represents the argument types of one of the value completion signatures.
Exposition Only
as-except-ptr(err)
Turns err smartly into an exception_ptr:
-
if
same_as<decay_t<decltype(err)>, exception_ptr>⇒err -
else if
same_as<decay_t<decltype(err)>, error_code>⇒make_exception_ptr(system_error(err)) -
else
make_exception_ptr(err)
awaitable-sender<Sndr, Promise>
The concept check awaitable-sender<Sndr, Promise> determines if the Sndr could work with the environment provided by Promise and if Promise supports a suitable unhandled_stopped() method.
concept class-type<T>
Determines if the type T is a decayed class type: decays-to<T, T> && is_class_v<T>
COMMON-DOMAIN(domains...)
The expression COMMON-DOMAIN(domains…) is
-
common_type_t<decltype(auto(domains))…>()if this expression is valid -
indeterminate_domain<decltype(auto(domains))…>()with duplicates removed from the template arguments
COMPL-DOMAIN<Tag>(sndr, ev...)
The expression COMPL-DOMAIN<Tag>(sndr, ev…) gets sndr`s completion domain given the optional environment `ev…:
-
get_completion_domain(get_env(sndr), ev..)if this expression is well-formed, -
indeterminate_domain()otherwise.
Note: it seems this exposition-only name is actually unused!
concept completion-signature<Signature>
This concept determines if the type Signature is a completion signature, i.e., if it has one of these three forms:
-
set_value_t(T…) -
set_error_t(T) -
set_stopped_t()
concept decays-to<From, To>
Determines if To is the result of decaying the type From: same_as<decay_t<From>, To>
FWD-ENV(env)
The expression FWD-ENV(env) yields a queryable object q supporting only forwardable queries. Let qry be a query object and a… be a possibly emnpty pack of arguments. Then q.query(qry, a…) is
-
equivalent to
env.query(qry, a…)ifforwarding_query(qry)istrue -
ill-formed if
forwarding_query(qry)isfalse
FWD-ENV-T(Env)
The type FWD-ENV-T(Env) is decltype(FWD-ENV(decl_val<Env>())).
gather-signatures<Tag, Signatures, Tuple, Variant>
The template specializaton gather-signatures<Tag, Signatures, Tuple, Variant> represents the completion signatures in the type list Signatures using Tag (one of set_value_t, set_error_t, or set_stopped_t) as a Variant of Tuple`s. Each `Tuple has the element types of of one of the matching completion signatures.
concept has-completions<Rcvr, Completions>
This concept determines if an object of type Rcvr supports ech of the completion signatures in Completions.
HIDE-SCHED(q)
For a query object tag and arguments a… the expressions HIDE-SCHED(q).query(tag, a…) is
-
undefined if
decay_t<decltype(tag)>isget_scheduler_torget_domain_t -
equivalent to
q.query(tag, a…)otherwise
infallible-scheduler<Sched, Env>
Determines if Sched is a scheduler (i.e., scheduler<Sched> is true) and if sched’s sender has only a `set_value_t() completion signature when used with an environment with an unstoppable_token<Tok> stop token Tok. If the stop token Tok is not unstoppable_token<Tok> the completion signatures can include a set_stopped_t() completion signature in addition to the set_value_t() completion signature.
JOIN-ENV(ev1, ev2)
The expression JOIN-ENV(ev1, ev2) yields a queryable object env such that for a query qry and a pack of arguments a… the result of the expression env.query(qry, a…) is
-
equivalent to ev1.query(qry, a…)if this expression is well-formed, otherwise -
equivalent to ev2.query(qry, a…)if this expression is well-formed, otherwise -
ill-formed
make-sender(tag, data = empty{}, child...)
Creates and object of type basic-sender<decltype(tag), decay_t<decltype(data)>, decay_t<decltype(child)>…> that’s direct initialized with the forwarded arguments.
MAKE-ENV(qry, value)
The expression MAKE-ENV(qry, value) creates a queryable object env such that for a pack of arguments a … the expression env.query(qry, a…) yields value.
constexpr bool MATCHING-SIG<F1, F2>
Determines if the two function signatures F1 and F2 match:
If same_as<F1, R1(A1…)> and same_as<F2, R2(A2…)> then MATCHING-SIG<F1, F2> == same_as<R1(A1&&…), R2(A2&&…)>.
concept movable-value<T>
Determines if objects of type T are movable, non-array values: move_constructible<decay_t<T>> && constructible_from<decay_t<T>> && (!is_array_v<remove_reference_t<T>>)
struct product-type<T...>
The type product-type<T…> is a tuple-like type. Instead of constructors it supports only direct initialization, allowing it to hold inplace constructed elements. It supports p.get<I>() and p.apply(fun) member functions.
concept queryable<T>
Determines if objects of type T are queryable: destructible<T>. The semantic implication is that using the queryable object with query objects behave as required.
query-with-default(tag, env, value)
Returns
-
tag(env)if this expression is well-formed -
valueotherwise
concept receiver-of<Rcvr, Signatures>
This concept determines if an object of type Rcvr is a receiver (i.e., receiver<Rcvr> is true) and supports each of the completion signatures in Signatures.
SCHED-ENV(sch)
The expression SCHED-ENV(sch) yields a queryable o such that
-
get_start_scheduler(o)is equivalent toget_start_scheduler(get_env(o)) -
get_domain(o)is equivalent toget_start_scheduler(get_env(o))
scope-join-t
The type scope-join-t is used with basic-sender to create a sender which completes when a counting scope becomes closed and empty.