344 lines
14 KiB
Markdown
344 lines
14 KiB
Markdown
[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)
|