[exec.async.ops]

# 33 Execution control library [[exec]](./#exec)

## 33.3 Asynchronous operations [exec.async.ops]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L172)

An [*execution resource*](#def:resource,execution "33.3 Asynchronous operations [exec.async.ops]") is a program entity that manages
a (possibly dynamic) set of execution agents ([[thread.req.lockable.general]](thread.req.lockable.general "32.2.5.1 General")),
which it uses to execute parallel work on behalf of callers[.](#1.sentence-1)

[*Example [1](#example-1)*:

The currently active thread,
a system-provided thread pool, and
uses of an API associated with an external hardware accelerator
are all examples of execution resources[.](#1.sentence-2)

â *end example*]

Execution resources execute asynchronous operations[.](#1.sentence-3)

An execution resource is either valid or invalid[.](#1.sentence-4)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L185)

An [*asynchronous operation*](#def:operation,asynchronous "33.3 Asynchronous operations [exec.async.ops]") is
a distinct unit of program execution that

- [(2.1)](#2.1)

  is explicitly created;

- [(2.2)](#2.2)

  can be explicitly started once at most;

- [(2.3)](#2.3)

  once started, eventually completes exactly once
with a (possibly empty) set of result datums and
in exactly one of three [*dispositions*](#def:disposition "33.3 Asynchronous operations [exec.async.ops]"):
success, failure, or cancellation;
  * [(2.3.1)](#2.3.1)

      A successful completion, also known as a [*value completion*](#def:completion,value "33.3 Asynchronous operations [exec.async.ops]"),
can have an arbitrary number of result datums[.](#2.3.1.sentence-1)

  * [(2.3.2)](#2.3.2)

      A failure completion, also known as an [*error completion*](#def:completion,error "33.3 Asynchronous operations [exec.async.ops]"),
has a single result datum[.](#2.3.2.sentence-1)

  * [(2.3.3)](#2.3.3)

      A cancellation completion, also known as a [*stopped completion*](#def:completion,stopped "33.3 Asynchronous operations [exec.async.ops]"),
has no result datum[.](#2.3.3.sentence-1)

   An asynchronous operation's [*async result*](#def:result,async "33.3 Asynchronous operations [exec.async.ops]") is its disposition and its (possibly empty) set of result datums[.](#2.3.sentence-2)

- [(2.4)](#2.4)

  can complete on a different execution resource
than the execution resource on which it started; and

- [(2.5)](#2.5)

  can create and start other asynchronous operations
called [*child operations*](#def:operations,child "33.3 Asynchronous operations [exec.async.ops]")[.](#2.5.sentence-1)
  A child operation is an asynchronous operation
that is created by the parent operation and,
if started, completes before the parent operation completes[.](#2.5.sentence-2)
  A [*parent operation*](#def:operation,parent "33.3 Asynchronous operations [exec.async.ops]") is the asynchronous operation
that created a particular child operation[.](#2.5.sentence-3)

[*Note [1](#note-1)*:

An asynchronous operation can execute synchronously;
that is, it can complete during the execution of its start operation
on the thread of execution that started it[.](#2.sentence-2)

â *end note*]

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L229)

An asynchronous operation has associated state
known as its [*operation state*](#def:state,operation "33.3 Asynchronous operations [exec.async.ops]")[.](#3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L233)

An asynchronous operation has an associated environment[.](#4.sentence-1)

An [*environment*](#def:environment "33.3 Asynchronous operations [exec.async.ops]") is a queryable object ([[exec.queryable]](exec.queryable "33.2 Queries and queryables"))
representing the execution-time properties of the operation's caller[.](#4.sentence-2)

The caller of an asynchronous operation is
its parent operation or the function that created it[.](#4.sentence-3)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L240)

An asynchronous operation has an associated receiver[.](#5.sentence-1)

A [*receiver*](#def:receiver "33.3 Asynchronous operations [exec.async.ops]") is an aggregation of three handlers
for the three asynchronous completion dispositions:

- [(5.1)](#5.1)

a value completion handler for a value completion,

- [(5.2)](#5.2)

an error completion handler for an error completion, and

- [(5.3)](#5.3)

a stopped completion handler for a stopped completion[.](#5.sentence-2)

A receiver has an associated environment[.](#5.sentence-3)

An asynchronous operation's operation state owns the operation's receiver[.](#5.sentence-4)

The environment of an asynchronous operation
is equal to its receiver's environment[.](#5.sentence-5)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L254)

For each completion disposition, there is a [*completion function*](#def:function,completion "33.3 Asynchronous operations [exec.async.ops]")[.](#6.sentence-1)

A completion function is
a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))
that accepts an asynchronous operation's receiver as the first argument and
the result datums of the asynchronous operation as additional arguments[.](#6.sentence-2)

The value completion function invokes
the receiver's value completion handler with the value result datums;
likewise for the error completion function and the stopped completion function[.](#6.sentence-3)

A completion function has
an associated type known as its [*completion tag*](#def:tag,completion "33.3 Asynchronous operations [exec.async.ops]") that is the unqualified type of the completion function[.](#6.sentence-4)

A valid invocation of a completion function is called
a [*completion operation*](#def:operation,completion "33.3 Asynchronous operations [exec.async.ops]")[.](#6.sentence-5)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L269)

The [*lifetime of an asynchronous operation*](#def:lifetime_of_an_asynchronous_operation "33.3 Asynchronous operations [exec.async.ops]"),
also known as the operation's [*async lifetime*](#def:async_lifetime "33.3 Asynchronous operations [exec.async.ops]"),
begins when its start operation begins executing and
ends when its completion operation begins executing[.](#7.sentence-1)

If the lifetime of an asynchronous operation's associated operation state
ends before the lifetime of the asynchronous operation,
the behavior is undefined[.](#7.sentence-2)

After an asynchronous operation executes a completion operation,
its associated operation state is invalid[.](#7.sentence-3)

Accessing any part of an invalid operation state is undefined behavior[.](#7.sentence-4)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L281)

An asynchronous operation shall not execute a completion operation
before its start operation has begun executing[.](#8.sentence-1)

After its start operation has begun executing,
exactly one completion operation shall execute[.](#8.sentence-2)

The lifetime of an asynchronous operation's operation state can end
during the execution of the completion operation[.](#8.sentence-3)

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L289)

A [*sender*](#def:sender "33.3 Asynchronous operations [exec.async.ops]") is a factory for one or more asynchronous operations[.](#9.sentence-1)

[*Connecting*](#def:connect "33.3 Asynchronous operations [exec.async.ops]") a sender and a receiver creates
an asynchronous operation[.](#9.sentence-2)

The asynchronous operation's associated receiver is equal to
the receiver used to create it, and
its associated environment is equal to
the environment associated with the receiver used to create it[.](#9.sentence-3)

The lifetime of an asynchronous operation's associated operation state
does not depend on the lifetimes of either the sender or the receiver
from which it was created[.](#9.sentence-4)

A sender is started when it is connected to a receiver and
the resulting asynchronous operation is started[.](#9.sentence-5)

A sender's async result is the async result of the asynchronous operation
created by connecting it to a receiver[.](#9.sentence-6)

A sender sends its results by way of the asynchronous operation(s) it produces,
and a receiver receives those results[.](#9.sentence-7)

A sender is either valid or invalid;
it becomes invalid when its parent sender (see below) becomes invalid[.](#9.sentence-8)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L309)

A [*scheduler*](#def:scheduler "33.3 Asynchronous operations [exec.async.ops]") is an abstraction of an execution resource
with a uniform, generic interface for scheduling work onto that resource[.](#10.sentence-1)

It is a factory for senders
whose asynchronous operations execute value completion operations
on an execution agent belonging to
the scheduler's associated execution resource[.](#10.sentence-2)

A [*schedule-expression*](#def:schedule-expression "33.3 Asynchronous operations [exec.async.ops]") obtains such a sender from a scheduler[.](#10.sentence-3)

A [*schedule sender*](#def:schedule_sender "33.3 Asynchronous operations [exec.async.ops]") is the result of a schedule expression[.](#10.sentence-4)

On success, an asynchronous operation produced by a schedule sender executes
a value completion operation with an empty set of result datums[.](#10.sentence-5)

Multiple schedulers can refer to the same execution resource[.](#10.sentence-6)

A scheduler can be valid or invalid[.](#10.sentence-7)

A scheduler becomes invalid when the execution resource to which it refers
becomes invalid,
as do any schedule senders obtained from the scheduler, and
any operation states obtained from those senders[.](#10.sentence-8)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L327)

An asynchronous operation has one or more associated completion schedulers
for each of its possible dispositions[.](#11.sentence-1)

A [*completion scheduler*](#def:completion_scheduler "33.3 Asynchronous operations [exec.async.ops]") is a scheduler
whose associated execution resource is used to execute
a completion operation for an asynchronous operation[.](#11.sentence-2)

A value completion scheduler is a scheduler
on which an asynchronous operation's value completion operation can execute[.](#11.sentence-3)

Likewise for error completion schedulers and stopped completion schedulers[.](#11.sentence-4)

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L337)

A sender has an associated queryable object ([[exec.queryable]](exec.queryable "33.2 Queries and queryables"))
known as its [*attributes*](#def:attribute "33.3 Asynchronous operations [exec.async.ops]") that describes various characteristics of the sender and
of the asynchronous operation(s) it produces[.](#12.sentence-1)

For each disposition,
there is a query object for reading the associated completion scheduler
from a sender's attributes;
i.e., a value completion scheduler query object
for reading a sender's value completion scheduler, etc[.](#12.sentence-2)

If a completion scheduler query is well-formed,
the returned completion scheduler is unique
for that disposition for any asynchronous operation the sender creates[.](#12.sentence-3)

A schedule sender is required to have a value completion scheduler attribute
whose value is equal to the scheduler that produced the schedule sender[.](#12.sentence-4)

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L353)

A [*completion signature*](#def:completion_signature "33.3 Asynchronous operations [exec.async.ops]") is a function type
that describes a completion operation[.](#13.sentence-1)

An asynchronous operation has a finite set of possible completion signatures
corresponding to the completion operations
that the asynchronous operation potentially evaluates ([[basic.def.odr]](basic.def.odr "6.3 One-definition rule"))[.](#13.sentence-2)

For a completion function set,
receiver rcvr, and
pack of arguments args,
let c be the completion operation set(rcvr, args...), and
let F be
the function type decltype(auto(set))(decltype((args))...)[.](#13.sentence-3)

A completion signature Sig is associated with c if and only if*MATCHING-SIG*(Sig, F) is true ([[exec.general]](exec.general "33.1 General"))[.](#13.sentence-4)

Together, a sender type and an environment type Env determine
the set of completion signatures of an asynchronous operation
that results from connecting the sender with a receiver
that has an environment of type Env[.](#13.sentence-5)

The type of the receiver does not affect
an asynchronous operation's completion signatures,
only the type of the receiver's environment[.](#13.sentence-6)

A [*non-dependent sender*](#def:sender,non-dependent "33.3 Asynchronous operations [exec.async.ops]") is a sender type
whose completion signatures are knowable
independent of an execution environment[.](#13.sentence-7)

[14](#14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L379)

A sender algorithm is a function that takes and/or returns a sender[.](#14.sentence-1)

There are three categories of sender algorithms:

- [(14.1)](#14.1)

  A [*sender factory*](#def:sender_factory "33.3 Asynchronous operations [exec.async.ops]") is a function
that takes non-senders as arguments and that returns a sender[.](#14.1.sentence-1)

- [(14.2)](#14.2)

  A [*sender adaptor*](#def:sender_adaptor "33.3 Asynchronous operations [exec.async.ops]") is a function
that constructs and returns a parent sender
from a set of one or more child senders and
a (possibly empty) set of additional arguments[.](#14.2.sentence-1)
  An asynchronous operation created by a parent sender is
a parent operation to the child operations created by the child senders[.](#14.2.sentence-2)

- [(14.3)](#14.3)

  A [*sender consumer*](#def:sender_consumer "33.3 Asynchronous operations [exec.async.ops]") is a function
that takes one or more senders and
a (possibly empty) set of additional arguments, and
whose return type is not the type of a sender[.](#14.3.sentence-1)
