Init
This commit is contained in:
298
cppdraft/exec/run/loop.md
Normal file
298
cppdraft/exec/run/loop.md
Normal file
@@ -0,0 +1,298 @@
|
||||
[exec.run.loop]
|
||||
|
||||
# 33 Execution control library [[exec]](./#exec)
|
||||
|
||||
## 33.12 Execution contexts [[exec.ctx]](exec.ctx#exec.run.loop)
|
||||
|
||||
### 33.12.1 execution::run_loop [exec.run.loop]
|
||||
|
||||
#### [33.12.1.1](#general) General [[exec.run.loop.general]](exec.run.loop.general)
|
||||
|
||||
[1](#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[.](#general-1.sentence-1)
|
||||
|
||||
It maintains a thread-safe first-in-first-out queue of work[.](#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[.](#general-1.sentence-3)
|
||||
|
||||
[2](#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.1 General [exec.run.loop.general]") that corresponds to the number of work items that are in its queue[.](#general-2.sentence-1)
|
||||
|
||||
Additionally, a run_loop instance has an associated state
|
||||
that can be one of[*starting*](#def:starting "33.12.1.1 General [exec.run.loop.general]"), [*running*](#def:running "33.12.1.1 General [exec.run.loop.general]"), [*finishing*](#def:finishing "33.12.1.1 General [exec.run.loop.general]"), or [*finished*](#def:finished "33.12.1.1 General [exec.run.loop.general]")[.](#general-2.sentence-2)
|
||||
|
||||
[3](#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[.](#general-3.sentence-1)
|
||||
|
||||
The member functions*pop-front*, *push-back*, and finish execute atomically[.](#general-3.sentence-2)
|
||||
|
||||
[4](#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[.](#general-4.sentence-1)
|
||||
|
||||
namespace std::execution {class [run_loop](#lib:run_loop "33.12.1.1 General [exec.run.loop.general]") {// [[exec.run.loop.types]](#types "33.12.1.2 Associated 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]](#members "33.12.1.4 Member 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]](#ctor "33.12.1.3 Constructor and destructor"), constructor and destructor run_loop() noexcept;
|
||||
run_loop(run_loop&&) = delete; ~run_loop(); // [[exec.run.loop.members]](#members "33.12.1.4 Member functions"), member functions*run-loop-scheduler* get_scheduler(); void run(); void finish(); };}
|
||||
|
||||
#### [33.12.1.2](#types) Associated types [[exec.run.loop.types]](exec.run.loop.types)
|
||||
|
||||
[ð](#types-itemdecl:1)
|
||||
|
||||
`class run-loop-scheduler;
|
||||
`
|
||||
|
||||
[1](#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.6 Schedulers [exec.sched]")[.](#types-1.sentence-1)
|
||||
|
||||
[2](#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[.](#types-2.sentence-1)
|
||||
|
||||
[3](#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[.](#types-3.sentence-1)
|
||||
|
||||
[4](#types-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6397)
|
||||
|
||||
Let *sch* be an expression of type *run-loop-scheduler*[.](#types-4.sentence-1)
|
||||
|
||||
The expression schedule(*sch*) has type *run-loop-
|
||||
sender* and
|
||||
is not potentially-throwing if *sch* is not potentially-throwing[.](#types-4.sentence-2)
|
||||
|
||||
[ð](#types-itemdecl:2)
|
||||
|
||||
`class run-loop-sender;
|
||||
`
|
||||
|
||||
[5](#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.3 Sender concepts [exec.snd.concepts]")[.](#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](#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[.](#types-6.sentence-1)
|
||||
|
||||
[7](#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.1 Receiver concepts [exec.recv.concepts]")<decltype((*rcvr*)), CS> is true where CS is the completion_signatures specialization above[.](#types-7.sentence-1)
|
||||
|
||||
Let C be either set_value_t or set_stopped_t[.](#types-7.sentence-2)
|
||||
|
||||
Then:
|
||||
|
||||
- [(7.1)](#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[.](#types-7.1.sentence-1)
|
||||
|
||||
- [(7.2)](#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[.](#types-7.2.sentence-1)
|
||||
|
||||
[ð](#types-itemdecl:3)
|
||||
|
||||
`template<class Rcvr>
|
||||
struct run-loop-opstate;
|
||||
`
|
||||
|
||||
[8](#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*[.](#types-8.sentence-1)
|
||||
|
||||
[9](#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[.](#types-9.sentence-1)
|
||||
|
||||
Then:
|
||||
|
||||
- [(9.1)](#types-9.1)
|
||||
|
||||
The object to which *REC*(o) refers
|
||||
remains valid for the lifetime of the object to which o refers.
|
||||
|
||||
- [(9.2)](#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)](#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](#ctor) Constructor and destructor [[exec.run.loop.ctor]](exec.run.loop.ctor)
|
||||
|
||||
[ð](#lib:run_loop,constructor)
|
||||
|
||||
`run_loop() noexcept;
|
||||
`
|
||||
|
||||
[1](#ctor-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6489)
|
||||
|
||||
*Postconditions*: *count* is 0 and *state* is *starting*[.](#ctor-1.sentence-1)
|
||||
|
||||
[ð](#lib:run_loop,destructor)
|
||||
|
||||
`~run_loop();
|
||||
`
|
||||
|
||||
[2](#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.2 The std::terminate function"))[.](#ctor-2.sentence-1)
|
||||
|
||||
Otherwise, has no effects[.](#ctor-2.sentence-2)
|
||||
|
||||
#### [33.12.1.4](#members) Member functions [[exec.run.loop.members]](exec.run.loop.members)
|
||||
|
||||
[ð](#members-itemdecl:1)
|
||||
|
||||
`run-loop-opstate-base* pop-front();
|
||||
`
|
||||
|
||||
[1](#members-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6514)
|
||||
|
||||
*Effects*: Blocks ([[defns.block]](defns.block "3.6 block")) until one of the following conditions is true:
|
||||
|
||||
- [(1.1)](#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)](#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[.](#members-1.sentence-1)
|
||||
|
||||
[ð](#members-itemdecl:2)
|
||||
|
||||
`void push-back(run-loop-opstate-base* item);
|
||||
`
|
||||
|
||||
[2](#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[.](#members-2.sentence-1)
|
||||
|
||||
[3](#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[.](#members-3.sentence-1)
|
||||
|
||||
[ð](#lib:get_scheduler,run_loop)
|
||||
|
||||
`run-loop-scheduler get_scheduler();
|
||||
`
|
||||
|
||||
[4](#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[.](#members-4.sentence-1)
|
||||
|
||||
[ð](#lib:run,run_loop)
|
||||
|
||||
`void run();
|
||||
`
|
||||
|
||||
[5](#members-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6564)
|
||||
|
||||
*Preconditions*: *state* is either *starting* or *finishing*[.](#members-5.sentence-1)
|
||||
|
||||
[6](#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[.](#members-6.sentence-1)
|
||||
|
||||
Then, equivalent to:while (auto* op = *pop-front*()) { op->*execute*();}
|
||||
|
||||
[7](#members-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6580)
|
||||
|
||||
*Remarks*: When *state* changes, it does so without introducing data races[.](#members-7.sentence-1)
|
||||
|
||||
[ð](#lib:finish,run_loop)
|
||||
|
||||
`void finish();
|
||||
`
|
||||
|
||||
[8](#members-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6591)
|
||||
|
||||
*Preconditions*: *state* is either *starting* or *running*[.](#members-8.sentence-1)
|
||||
|
||||
[9](#members-9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6595)
|
||||
|
||||
*Effects*: Changes *state* to *finishing*[.](#members-9.sentence-1)
|
||||
|
||||
[10](#members-10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6599)
|
||||
|
||||
*Synchronization*: finish synchronizes with the *pop-front* operation
|
||||
that returns nullptr[.](#members-10.sentence-1)
|
||||
34
cppdraft/exec/run/loop/ctor.md
Normal file
34
cppdraft/exec/run/loop/ctor.md
Normal file
@@ -0,0 +1,34 @@
|
||||
[exec.run.loop.ctor]
|
||||
|
||||
# 33 Execution control library [[exec]](./#exec)
|
||||
|
||||
## 33.12 Execution contexts [[exec.ctx]](exec.ctx#exec.run.loop.ctor)
|
||||
|
||||
### 33.12.1 execution::run_loop [[exec.run.loop]](exec.run.loop#ctor)
|
||||
|
||||
#### 33.12.1.3 Constructor and destructor [exec.run.loop.ctor]
|
||||
|
||||
[ð](#lib:run_loop,constructor)
|
||||
|
||||
`run_loop() noexcept;
|
||||
`
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6489)
|
||||
|
||||
*Postconditions*: *count* is 0 and *state* is *starting*[.](#1.sentence-1)
|
||||
|
||||
[ð](#lib:run_loop,destructor)
|
||||
|
||||
`~run_loop();
|
||||
`
|
||||
|
||||
[2](#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.2 The std::terminate function"))[.](#2.sentence-1)
|
||||
|
||||
Otherwise, has no effects[.](#2.sentence-2)
|
||||
47
cppdraft/exec/run/loop/general.md
Normal file
47
cppdraft/exec/run/loop/general.md
Normal file
@@ -0,0 +1,47 @@
|
||||
[exec.run.loop.general]
|
||||
|
||||
# 33 Execution control library [[exec]](./#exec)
|
||||
|
||||
## 33.12 Execution contexts [[exec.ctx]](exec.ctx#exec.run.loop.general)
|
||||
|
||||
### 33.12.1 execution::run_loop [[exec.run.loop]](exec.run.loop#general)
|
||||
|
||||
#### 33.12.1.1 General [exec.run.loop.general]
|
||||
|
||||
[1](#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[.](#1.sentence-1)
|
||||
|
||||
It maintains a thread-safe first-in-first-out queue of work[.](#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[.](#1.sentence-3)
|
||||
|
||||
[2](#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.1 General [exec.run.loop.general]") that corresponds to the number of work items that are in its queue[.](#2.sentence-1)
|
||||
|
||||
Additionally, a run_loop instance has an associated state
|
||||
that can be one of[*starting*](#def:starting "33.12.1.1 General [exec.run.loop.general]"), [*running*](#def:running "33.12.1.1 General [exec.run.loop.general]"), [*finishing*](#def:finishing "33.12.1.1 General [exec.run.loop.general]"), or [*finished*](#def:finished "33.12.1.1 General [exec.run.loop.general]")[.](#2.sentence-2)
|
||||
|
||||
[3](#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[.](#3.sentence-1)
|
||||
|
||||
The member functions*pop-front*, *push-back*, and finish execute atomically[.](#3.sentence-2)
|
||||
|
||||
[4](#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[.](#4.sentence-1)
|
||||
|
||||
namespace std::execution {class [run_loop](#lib:run_loop "33.12.1.1 General [exec.run.loop.general]") {// [[exec.run.loop.types]](exec.run.loop.types "33.12.1.2 Associated 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.4 Member 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.3 Constructor 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.4 Member functions"), member functions*run-loop-scheduler* get_scheduler(); void run(); void finish(); };}
|
||||
112
cppdraft/exec/run/loop/members.md
Normal file
112
cppdraft/exec/run/loop/members.md
Normal file
@@ -0,0 +1,112 @@
|
||||
[exec.run.loop.members]
|
||||
|
||||
# 33 Execution control library [[exec]](./#exec)
|
||||
|
||||
## 33.12 Execution contexts [[exec.ctx]](exec.ctx#exec.run.loop.members)
|
||||
|
||||
### 33.12.1 execution::run_loop [[exec.run.loop]](exec.run.loop#members)
|
||||
|
||||
#### 33.12.1.4 Member functions [exec.run.loop.members]
|
||||
|
||||
[ð](#itemdecl:1)
|
||||
|
||||
`run-loop-opstate-base* pop-front();
|
||||
`
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6514)
|
||||
|
||||
*Effects*: Blocks ([[defns.block]](defns.block "3.6 block")) until one of the following conditions is true:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
*count* is 0 and *state* is *finishing*,
|
||||
in which case *pop-front* sets *state* to *finished* and returns nullptr; or
|
||||
|
||||
- [(1.2)](#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[.](#1.sentence-1)
|
||||
|
||||
[ð](#itemdecl:2)
|
||||
|
||||
`void push-back(run-loop-opstate-base* item);
|
||||
`
|
||||
|
||||
[2](#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[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6540)
|
||||
|
||||
*Synchronization*: This operation synchronizes with
|
||||
the *pop-front* operation that obtains item[.](#3.sentence-1)
|
||||
|
||||
[ð](#lib:get_scheduler,run_loop)
|
||||
|
||||
`run-loop-scheduler get_scheduler();
|
||||
`
|
||||
|
||||
[4](#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[.](#4.sentence-1)
|
||||
|
||||
[ð](#lib:run,run_loop)
|
||||
|
||||
`void run();
|
||||
`
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6564)
|
||||
|
||||
*Preconditions*: *state* is either *starting* or *finishing*[.](#5.sentence-1)
|
||||
|
||||
[6](#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[.](#6.sentence-1)
|
||||
|
||||
Then, equivalent to:while (auto* op = *pop-front*()) { op->*execute*();}
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6580)
|
||||
|
||||
*Remarks*: When *state* changes, it does so without introducing data races[.](#7.sentence-1)
|
||||
|
||||
[ð](#lib:finish,run_loop)
|
||||
|
||||
`void finish();
|
||||
`
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6591)
|
||||
|
||||
*Preconditions*: *state* is either *starting* or *running*[.](#8.sentence-1)
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6595)
|
||||
|
||||
*Effects*: Changes *state* to *finishing*[.](#9.sentence-1)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6599)
|
||||
|
||||
*Synchronization*: finish synchronizes with the *pop-front* operation
|
||||
that returns nullptr[.](#10.sentence-1)
|
||||
126
cppdraft/exec/run/loop/types.md
Normal file
126
cppdraft/exec/run/loop/types.md
Normal file
@@ -0,0 +1,126 @@
|
||||
[exec.run.loop.types]
|
||||
|
||||
# 33 Execution control library [[exec]](./#exec)
|
||||
|
||||
## 33.12 Execution contexts [[exec.ctx]](exec.ctx#exec.run.loop.types)
|
||||
|
||||
### 33.12.1 execution::run_loop [[exec.run.loop]](exec.run.loop#types)
|
||||
|
||||
#### 33.12.1.2 Associated types [exec.run.loop.types]
|
||||
|
||||
[ð](#itemdecl:1)
|
||||
|
||||
`class run-loop-scheduler;
|
||||
`
|
||||
|
||||
[1](#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.6 Schedulers [exec.sched]")[.](#1.sentence-1)
|
||||
|
||||
[2](#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[.](#2.sentence-1)
|
||||
|
||||
[3](#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[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6397)
|
||||
|
||||
Let *sch* be an expression of type *run-loop-scheduler*[.](#4.sentence-1)
|
||||
|
||||
The expression schedule(*sch*) has type *run-loop-
|
||||
sender* and
|
||||
is not potentially-throwing if *sch* is not potentially-throwing[.](#4.sentence-2)
|
||||
|
||||
[ð](#itemdecl:2)
|
||||
|
||||
`class run-loop-sender;
|
||||
`
|
||||
|
||||
[5](#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.3 Sender concepts [exec.snd.concepts]")[.](#5.sentence-1)
|
||||
|
||||
completion_signatures_of_t<*run-
|
||||
loop-sender*> iscompletion_signatures<set_value_t(), set_error_t(exception_ptr), set_stopped_t()>
|
||||
|
||||
[6](#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[.](#6.sentence-1)
|
||||
|
||||
[7](#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.1 Receiver concepts [exec.recv.concepts]")<decltype((*rcvr*)), CS> is true where CS is the completion_signatures specialization above[.](#7.sentence-1)
|
||||
|
||||
Let C be either set_value_t or set_stopped_t[.](#7.sentence-2)
|
||||
|
||||
Then:
|
||||
|
||||
- [(7.1)](#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[.](#7.1.sentence-1)
|
||||
|
||||
- [(7.2)](#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[.](#7.2.sentence-1)
|
||||
|
||||
[ð](#itemdecl:3)
|
||||
|
||||
`template<class Rcvr>
|
||||
struct run-loop-opstate;
|
||||
`
|
||||
|
||||
[8](#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*[.](#8.sentence-1)
|
||||
|
||||
[9](#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[.](#9.sentence-1)
|
||||
|
||||
Then:
|
||||
|
||||
- [(9.1)](#9.1)
|
||||
|
||||
The object to which *REC*(o) refers
|
||||
remains valid for the lifetime of the object to which o refers.
|
||||
|
||||
- [(9.2)](#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)](#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());}
|
||||
Reference in New Issue
Block a user