Files
cppdraft_translate/cppdraft/exec/ctx.md
2025-10-25 03:02:53 +03:00

299 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[exec.ctx]
# 33 Execution control library [[exec]](./#exec)
## 33.12 Execution contexts [exec.ctx]
### [33.12.1](#exec.run.loop) execution::run_loop [[exec.run.loop]](exec.run.loop)
#### [33.12.1.1](#exec.run.loop.general) General [[exec.run.loop.general]](exec.run.loop.general)
[1](#exec.run.loop.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6321)
A run_loop is an execution resource on which work can be scheduled[.](#exec.run.loop.general-1.sentence-1)
It maintains a thread-safe first-in-first-out queue of work[.](#exec.run.loop.general-1.sentence-2)
Its run member function removes elements from the queue and
executes them in a loop on the thread of execution that calls run[.](#exec.run.loop.general-1.sentence-3)
[2](#exec.run.loop.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6327)
A run_loop instance has an associated [*count*](#def:count "33.12.1.1General[exec.run.loop.general]") that corresponds to the number of work items that are in its queue[.](#exec.run.loop.general-2.sentence-1)
Additionally, a run_loop instance has an associated state
that can be one of[*starting*](#def:starting "33.12.1.1General[exec.run.loop.general]"), [*running*](#def:running "33.12.1.1General[exec.run.loop.general]"), [*finishing*](#def:finishing "33.12.1.1General[exec.run.loop.general]"), or [*finished*](#def:finished "33.12.1.1General[exec.run.loop.general]")[.](#exec.run.loop.general-2.sentence-2)
[3](#exec.run.loop.general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6334)
Concurrent invocations of the member functions of run_loop other than run and its destructor do not introduce data races[.](#exec.run.loop.general-3.sentence-1)
The member functions*pop-front*, *push-back*, and finish execute atomically[.](#exec.run.loop.general-3.sentence-2)
[4](#exec.run.loop.general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6341)
*Recommended practice*: Implementations should use an intrusive queue of operation states
to hold the work units to make scheduling allocation-free[.](#exec.run.loop.general-4.sentence-1)
namespace std::execution {class [run_loop](#lib:run_loop "33.12.1.1General[exec.run.loop.general]") {// [[exec.run.loop.types]](#exec.run.loop.types "33.12.1.2Associated types"), associated typesclass *run-loop-scheduler*; // *exposition only*class *run-loop-sender*; // *exposition only*struct *run-loop-opstate-base* { // *exposition only*virtual void *execute*() = 0; // *exposition only* run_loop* *loop*; // *exposition only**run-loop-opstate-base** *next*; // *exposition only*}; template<class Rcvr>using *run-loop-opstate* = *unspecified*; // *exposition only*// [[exec.run.loop.members]](#exec.run.loop.members "33.12.1.4Member functions"), member functions*run-loop-opstate-base** *pop-front*(); // *exposition only*void *push-back*(*run-loop-opstate-base**); // *exposition only*public:// [[exec.run.loop.ctor]](#exec.run.loop.ctor "33.12.1.3Constructor and destructor"), constructor and destructor run_loop() noexcept;
run_loop(run_loop&&) = delete; ~run_loop(); // [[exec.run.loop.members]](#exec.run.loop.members "33.12.1.4Member functions"), member functions*run-loop-scheduler* get_scheduler(); void run(); void finish(); };}
#### [33.12.1.2](#exec.run.loop.types) Associated types [[exec.run.loop.types]](exec.run.loop.types)
[🔗](#exec.run.loop.types-itemdecl:1)
`class run-loop-scheduler;
`
[1](#exec.run.loop.types-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6384)
*run-loop-scheduler* is an unspecified type
that models [scheduler](exec.sched#concept:scheduler "33.6Schedulers[exec.sched]")[.](#exec.run.loop.types-1.sentence-1)
[2](#exec.run.loop.types-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6388)
Instances of *run-loop-scheduler* remain valid
until the end of the lifetime of the run_loop instance
from which they were obtained[.](#exec.run.loop.types-2.sentence-1)
[3](#exec.run.loop.types-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6393)
Two instances of *run-loop-scheduler* compare equal
if and only if they were obtained from the same run_loop instance[.](#exec.run.loop.types-3.sentence-1)
[4](#exec.run.loop.types-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6397)
Let *sch* be an expression of type *run-loop-scheduler*[.](#exec.run.loop.types-4.sentence-1)
The expression schedule(*sch*) has type *run-loop-
sender* and
is not potentially-throwing if *sch* is not potentially-throwing[.](#exec.run.loop.types-4.sentence-2)
[🔗](#exec.run.loop.types-itemdecl:2)
`class run-loop-sender;
`
[5](#exec.run.loop.types-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6407)
*run-loop-sender* is an exposition-only type
that satisfies [sender](exec.snd.concepts#concept:sender "33.9.3Sender concepts[exec.snd.concepts]")[.](#exec.run.loop.types-5.sentence-1)
completion_signatures_of_t<*run-
loop-sender*> iscompletion_signatures<set_value_t(), set_error_t(exception_ptr), set_stopped_t()>
[6](#exec.run.loop.types-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6415)
An instance of *run-loop-sender* remains valid
until the end of the lifetime of its associated run_loop instance[.](#exec.run.loop.types-6.sentence-1)
[7](#exec.run.loop.types-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6419)
Let *sndr* be an expression of type *run-loop-sender*,
let *rcvr* be an expression
such that [receiver_of](exec.recv.concepts#concept:receiver_of "33.7.1Receiver concepts[exec.recv.concepts]")<decltype((*rcvr*)), CS> is true where CS is the completion_signatures specialization above[.](#exec.run.loop.types-7.sentence-1)
Let C be either set_value_t or set_stopped_t[.](#exec.run.loop.types-7.sentence-2)
Then:
- [(7.1)](#exec.run.loop.types-7.1)
The expression connect(*sndr*, *rcvr*) has type *run-loop-opstate*<decay_t<decltype((*rcvr*))>> and is potentially-throwing if and only if(void(*sndr*), auto(*rcvr*)) is potentially-throwing[.](#exec.run.loop.types-7.1.sentence-1)
- [(7.2)](#exec.run.loop.types-7.2)
The expression get_completion_scheduler<C>(get_env(*sndr*)) is potentially-throwing if and only if *sndr* is potentially-throwing,
has type *run-loop-scheduler*, and
compares equal to the *run-loop-
scheduler* instance
from which *sndr* was obtained[.](#exec.run.loop.types-7.2.sentence-1)
[🔗](#exec.run.loop.types-itemdecl:3)
`template<class Rcvr>
struct run-loop-opstate;
`
[8](#exec.run.loop.types-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6445)
*run-loop-opstate*<Rcvr> inherits privately and unambiguously from *run-loop-opstate-base*[.](#exec.run.loop.types-8.sentence-1)
[9](#exec.run.loop.types-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6449)
Let o be a non-const lvalue of type *run-loop-opstate*<Rcvr>,
and let REC(o) be a non-const lvalue reference to an instance of type Rcvr that was initialized with the expression *rcvr* passed to the invocation of connect that returned o[.](#exec.run.loop.types-9.sentence-1)
Then:
- [(9.1)](#exec.run.loop.types-9.1)
The object to which *REC*(o) refers
remains valid for the lifetime of the object to which o refers.
- [(9.2)](#exec.run.loop.types-9.2)
The type *run-loop-opstate*<Rcvr> overrides*run-loop-opstate-base*::*execute*() such that o.*execute*() is equivalent to:if (get_stop_token(*REC*(o)).stop_requested()) { set_stopped(std::move(*REC*(o)));} else { set_value(std::move(*REC*(o)));}
- [(9.3)](#exec.run.loop.types-9.3)
The expression start(o) is equivalent to:try {o.*loop*->*push-back*(addressof(o));} catch(...) { set_error(std::move(*REC*(o)), current_exception());}
#### [33.12.1.3](#exec.run.loop.ctor) Constructor and destructor [[exec.run.loop.ctor]](exec.run.loop.ctor)
[🔗](#lib:run_loop,constructor)
`run_loop() noexcept;
`
[1](#exec.run.loop.ctor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6489)
*Postconditions*: *count* is 0 and *state* is *starting*[.](#exec.run.loop.ctor-1.sentence-1)
[🔗](#lib:run_loop,destructor)
`~run_loop();
`
[2](#exec.run.loop.ctor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6500)
*Effects*: If *count* is not 0 or if *state* is *running*,
invokes terminate ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#exec.run.loop.ctor-2.sentence-1)
Otherwise, has no effects[.](#exec.run.loop.ctor-2.sentence-2)
#### [33.12.1.4](#exec.run.loop.members) Member functions [[exec.run.loop.members]](exec.run.loop.members)
[🔗](#exec.run.loop.members-itemdecl:1)
`run-loop-opstate-base* pop-front();
`
[1](#exec.run.loop.members-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6514)
*Effects*: Blocks ([[defns.block]](defns.block "3.6block")) until one of the following conditions is true:
- [(1.1)](#exec.run.loop.members-1.1)
*count* is 0 and *state* is *finishing*,
in which case *pop-front* sets *state* to *finished* and returns nullptr; or
- [(1.2)](#exec.run.loop.members-1.2)
*count* is greater than 0,
in which case an item is removed from the front of the queue,*count* is decremented by 1, and
the removed item is returned[.](#exec.run.loop.members-1.sentence-1)
[🔗](#exec.run.loop.members-itemdecl:2)
`void push-back(run-loop-opstate-base* item);
`
[2](#exec.run.loop.members-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6535)
*Effects*: Adds item to the back of the queue and
increments *count* by 1[.](#exec.run.loop.members-2.sentence-1)
[3](#exec.run.loop.members-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6540)
*Synchronization*: This operation synchronizes with
the *pop-front* operation that obtains item[.](#exec.run.loop.members-3.sentence-1)
[🔗](#lib:get_scheduler,run_loop)
`run-loop-scheduler get_scheduler();
`
[4](#exec.run.loop.members-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6552)
*Returns*: An instance of *run-loop-scheduler* that can be used to schedule work onto this run_loop instance[.](#exec.run.loop.members-4.sentence-1)
[🔗](#lib:run,run_loop)
`void run();
`
[5](#exec.run.loop.members-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6564)
*Preconditions*: *state* is either *starting* or *finishing*[.](#exec.run.loop.members-5.sentence-1)
[6](#exec.run.loop.members-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6568)
*Effects*: If *state* is *starting*,
sets the *state* to *running*,
otherwise leaves *state* unchanged[.](#exec.run.loop.members-6.sentence-1)
Then, equivalent to:while (auto* op = *pop-front*()) { op->*execute*();}
[7](#exec.run.loop.members-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6580)
*Remarks*: When *state* changes, it does so without introducing data races[.](#exec.run.loop.members-7.sentence-1)
[🔗](#lib:finish,run_loop)
`void finish();
`
[8](#exec.run.loop.members-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6591)
*Preconditions*: *state* is either *starting* or *running*[.](#exec.run.loop.members-8.sentence-1)
[9](#exec.run.loop.members-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6595)
*Effects*: Changes *state* to *finishing*[.](#exec.run.loop.members-9.sentence-1)
[10](#exec.run.loop.members-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6599)
*Synchronization*: finish synchronizes with the *pop-front* operation
that returns nullptr[.](#exec.run.loop.members-10.sentence-1)