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

117 lines
5.2 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.counting.scopes.general]
# 33 Execution control library [[exec]](./#exec)
## 33.14 Execution scope utilities [[exec.scope]](exec.scope#exec.counting.scopes.general)
### 33.14.2 Counting Scopes [[exec.counting.scopes]](exec.counting.scopes#general)
#### 33.14.2.1 General [exec.counting.scopes.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L7769)
Scopes of type simple_counting_scope and counting_scope maintain counts of associations[.](#1.sentence-1)
Let:
- [(1.1)](#1.1)
Scope be either simple_counting_scope or counting_scope,
- [(1.2)](#1.2)
scope be an object of type Scope,
- [(1.3)](#1.3)
tkn be an object of type Scope::token obtained from scope.get_token(),
- [(1.4)](#1.4)
jsndr be a sender obtained from scope.join(), and
- [(1.5)](#1.5)
op be an operation state obtained from
connecting jsndr to a receiver[.](#1.sentence-2)
During its lifetime scope goes through different states
which govern what operations are allowed and the result of these operations:
- [(1.6)](#1.6)
*unused*:
a newly constructed object starts in the *unused* state[.](#1.6.sentence-1)
- [(1.7)](#1.7)
*open*:
when tkn.try_associate() is called
while scope is in the *unused* state,scope moves to the *open* state[.](#1.7.sentence-1)
- [(1.8)](#1.8)
*open-and-joining*:
when the operation state op is started
while scope is in the *unused* or *open* state,scope moves to the *open-and-joining* state[.](#1.8.sentence-1)
- [(1.9)](#1.9)
*closed*:
when scope.close() is called
while scope is in the *open* state,scope moves to the *closed* state[.](#1.9.sentence-1)
- [(1.10)](#1.10)
*unused-and-closed*:
when scope.close() is called
while scope is in the *unused* state,scope moves to the *unused-and-closed* state[.](#1.10.sentence-1)
- [(1.11)](#1.11)
*closed-and-joining*:
when scope.close() is called
while scope is in the *open-and-joining* state or
the operation state op is started
while scope is in
the *closed* or *unused-and-closed* state,scope moves to the *closed-and-joining* state[.](#1.11.sentence-1)
- [(1.12)](#1.12)
*joined*:
when the count of associations drops to zero
while scope is in
the *open-and-joining* or *closed-and-joining* state,scope moves to the *joined* state[.](#1.12.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L7836)
*Recommended practice*: For simple_counting_scope and counting_scope,
implementations should store the state and the count of associations
in a single member of type size_t[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L7842)
Subclause [[exec.counting.scopes]](exec.counting.scopes "33.14.2Counting Scopes") makes use of
the following exposition-only entities:
struct *scope-join-t* {}; // *exposition only*enum *scope-state-type* { // *exposition only**unused*, // *exposition only**open*, // *exposition only**closed*, // *exposition only**open-and-joining*, // *exposition only**closed-and-joining*, // *exposition only**unused-and-closed*, // *exposition only**joined*, // *exposition only*};
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L7860)
The exposition-only class template *impls-for* ([[exec.snd.expos]](exec.snd.expos "33.9.2Exposition-only entities"))
is specialized for *scope-join-t* as follows:
namespace std::execution {template<>struct *impls-for*<*scope-join-t*> : *default-impls* {template<class Scope, class Rcvr>struct *state* { // *exposition only*struct *rcvr-t* { // *exposition only*using receiver_concept = receiver_t;
Rcvr& *rcvr*; // *exposition only*void set_value() && noexcept { execution::set_value(std::move(*rcvr*)); }template<class E>void set_error(E&& e) && noexcept { execution::set_error(std::move(*rcvr*), std::forward<E>(e)); }void set_stopped() && noexcept { execution::set_stopped(std::move(*rcvr*)); }decltype(auto) get_env() const noexcept {return execution::get_env(*rcvr*); }}; using *sched-sender* = // *exposition only*decltype(schedule(get_scheduler(get_env(declval<Rcvr&>())))); using *op-t* = // *exposition only* connect_result_t<*sched-sender*, *rcvr-t*>;
Scope* *scope*; // *exposition only* Rcvr& *receiver*; // *exposition only**op-t* *op*; // *exposition only**state*(Scope* scope, Rcvr& rcvr) // *exposition only*noexcept([*nothrow-callable*](functional.syn#concept:nothrow-callable "22.10.2Header <functional> synopsis[functional.syn]")<connect_t, *sched-sender*, *rcvr-t*>): *scope*(scope), *receiver*(rcvr), *op*(connect(schedule(get_scheduler(get_env(rcvr))), *rcvr-t*(rcvr))) {}void *complete*() noexcept { // *exposition only* start(*op*); }void *complete-inline*() noexcept { // *exposition only* set_value(std::move(*receiver*)); }}; static constexpr auto *get-state* = // *exposition only*[]<class Rcvr>(auto&& sender, Rcvr& receiver)noexcept(is_nothrow_constructible_v<*state*<Rcvr>, *data-type*<decltype(sender)>, Rcvr&>) {auto[_, self] = sender; return *state*(self, receiver); }; static constexpr auto *start* = // *exposition only*[](auto& s, auto&) noexcept {if (s.*scope*->*start-join-sender*(s)) s.*complete-inline*(); }; };}