Files
2025-10-25 03:02:53 +03:00

294 lines
15 KiB
Markdown
Raw Permalink 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.

[stoptoken.concepts]
# 32 Concurrency support library [[thread]](./#thread)
## 32.3 Stop tokens [[thread.stoptoken]](thread.stoptoken#stoptoken.concepts)
### 32.3.3 Stop token concepts [stoptoken.concepts]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L566)
The exposition-only [*stoppable-callback-for*](#concept:stoppable-callback-for "32.3.3Stop token concepts[stoptoken.concepts]") concept
checks for a callback compatible with a given Token type[.](#1.sentence-1)
template<class CallbackFn, class Token, class Initializer = CallbackFn>concept [*stoppable-callback-for*](#concept:stoppable-callback-for "32.3.3Stop token concepts[stoptoken.concepts]") = // *exposition only*[invocable](concept.invocable#concept:invocable "18.7.2Concept invocable[concept.invocable]")<CallbackFn> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<CallbackFn, Initializer> &&requires { typename stop_callback_for_t<Token, CallbackFn>; } &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<stop_callback_for_t<Token, CallbackFn>, const Token&, Initializer>;
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L578)
Let t and u be distinct, valid objects of type Token that reference the same logical stop state;
let init be an expression such that[same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<decltype(init), Initializer> is true; and
let SCB denote the type stop_callback_for_t<Token, CallbackFn>[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L585)
The concept[*stoppable-callback-for*](#concept:stoppable-callback-for "32.3.3Stop token concepts[stoptoken.concepts]")<CallbackFn, Token, Initializer> is modeled only if:
- [(3.1)](#3.1)
The following concepts are modeled:
* [(3.1.1)](#3.1.1)
[constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<SCB, Token, Initializer>
* [(3.1.2)](#3.1.2)
[constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<SCB, Token&, Initializer>
* [(3.1.3)](#3.1.3)
[constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<SCB, const Token, Initializer>
- [(3.2)](#3.2)
An object of type SCB has
an associated callback function of type CallbackFn[.](#3.2.sentence-1)
Let scb be an object of type SCB and
let callback_fn denote scb's associated callback function[.](#3.2.sentence-2)
Direct-non-list-initializing scb from
arguments t and init shall execute a [*stoppable callback registration*](#def:registration,stoppable_callback "32.3.3Stop token concepts[stoptoken.concepts]") as follows:
* [(3.2.1)](#3.2.1)
If t.stop_possible() is true:
+
[(3.2.1.1)](#3.2.1.1)
callback_fn shall be direct-initialized with init[.](#3.2.1.1.sentence-1)
+
[(3.2.1.2)](#3.2.1.2)
Construction of scb shall only throw exceptions
thrown by the initialization of callback_fn from init[.](#3.2.1.2.sentence-1)
+
[(3.2.1.3)](#3.2.1.3)
The callback invocation std::forward<CallbackFn>(callback_fn)() shall be registered with t's associated stop state as follows:
- [(3.2.1.3.1)](#3.2.1.3.1)
If t.stop_requested() evaluates to false at the time of registration,
the callback invocation is added to the stop state's list of callbacks
such that std::forward<CallbackFn>(
callback_fn)() is evaluated
if a stop request is made on the stop state[.](#3.2.1.3.1.sentence-1)
- [(3.2.1.3.2)](#3.2.1.3.2)
Otherwise, std::forward<CallbackFn>(callback_fn)() shall be immediately evaluated
on the thread executing scb's constructor, and
the callback invocation shall not be added to the list of callback invocations[.](#3.2.1.3.2.sentence-1)
If the callback invocation was added to stop state's list of callbacks,scb shall be associated with the stop state[.](#3.2.1.3.sentence-2)
* [(3.2.2)](#3.2.2)
[*Note [1](#note-1)*:
If t.stop_possible() is false,
there is no requirement
that the initialization of scb causes the initialization of callback_fn[.](#3.2.2.sentence-1)
— *end note*]
- [(3.3)](#3.3)
Destruction of scb shall execute
a [*stoppable callback deregistration*](#def:callback_deregistration,stoppable "32.3.3Stop token concepts[stoptoken.concepts]") as follows (in order):
* [(3.3.1)](#3.3.1)
If the constructor of scb did not register
a callback invocation with t's stop state,
then the stoppable callback deregistration shall have no effect
other than destroying callback_fn if it was constructed[.](#3.3.1.sentence-1)
* [(3.3.2)](#3.3.2)
Otherwise, the invocation of callback_fn shall be removed
from the associated stop state[.](#3.3.2.sentence-1)
* [(3.3.3)](#3.3.3)
If callback_fn is concurrently executing on another thread,
then the stoppable callback deregistration shall block ([[defns.block]](defns.block "3.6block"))
until the invocation of callback_fn returns
such that the return from the invocation of callback_fn strongly happens before ([[intro.races]](intro.races "6.10.2.2Data races"))
the destruction of callback_fn[.](#3.3.3.sentence-1)
* [(3.3.4)](#3.3.4)
If callback_fn is executing on the current thread,
then the destructor shall not block
waiting for the return from the invocation of callback_fn[.](#3.3.4.sentence-1)
* [(3.3.5)](#3.3.5)
A stoppable callback deregistration shall not block
on the completion of the invocation of some other callback
registered with the same logical stop state[.](#3.3.5.sentence-1)
* [(3.3.6)](#3.3.6)
The stoppable callback deregistration shall destroy callback_fn[.](#3.3.6.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L675)
The [stoppable_token](#concept:stoppable_token "32.3.3Stop token concepts[stoptoken.concepts]") concept checks
for the basic interface of a stop token
that is copyable and allows polling to see if stop has been requested and
also whether a stop request is possible[.](#4.sentence-1)
The [unstoppable_token](#concept:unstoppable_token "32.3.3Stop token concepts[stoptoken.concepts]") concept checks
for a [stoppable_token](#concept:stoppable_token "32.3.3Stop token concepts[stoptoken.concepts]") type that does not allow stopping[.](#4.sentence-2)
template<template<class> class>struct *check-type-alias-exists*; // *exposition only*template<class Token>concept [stoppable_token](#concept:stoppable_token "32.3.3Stop token concepts[stoptoken.concepts]") =requires (const Token tok) {typename *check-type-alias-exists*<Token::template callback_type>; { tok.stop_requested() } noexcept -> [same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<bool>; { tok.stop_possible() } noexcept -> [same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<bool>; { Token(tok) } noexcept; // see implicit expression variations ([[concepts.equality]](concepts.equality "18.2Equality preservation"))} &&[copyable](concepts.object#concept:copyable "18.6Object concepts[concepts.object]")<Token> &&[equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4Concept equality_­comparable[concept.equalitycomparable]")<Token>;
template<class Token>concept [unstoppable_token](#concept:unstoppable_token "32.3.3Stop token concepts[stoptoken.concepts]") =[stoppable_token](#concept:stoppable_token "32.3.3Stop token concepts[stoptoken.concepts]")<Token> &&requires (const Token tok) {requires bool_constant<(!tok.stop_possible())>::value; };
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L705)
An object whose type models [stoppable_token](#concept:stoppable_token "32.3.3Stop token concepts[stoptoken.concepts]") has at most one associated logical stop state[.](#5.sentence-1)
A [stoppable_token](#concept:stoppable_token "32.3.3Stop token concepts[stoptoken.concepts]") object with no associated stop state
is said to be [*disengaged*](#def:disengaged "32.3.3Stop token concepts[stoptoken.concepts]")[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L711)
Let SP be an evaluation of t.stop_possible() that is false, and
let SR be an evaluation of t.stop_requested() that is true[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L716)
The type Token models [stoppable_token](#concept:stoppable_token "32.3.3Stop token concepts[stoptoken.concepts]") only if:
- [(7.1)](#7.1)
Any evaluation of u.stop_possible() or u.stop_requested() that happens after ([[intro.races]](intro.races "6.10.2.2Data races")) SP is false[.](#7.1.sentence-1)
- [(7.2)](#7.2)
Any evaluation of u.stop_possible() or u.stop_requested() that happens after SR is true[.](#7.2.sentence-1)
- [(7.3)](#7.3)
For any types CallbackFn and Initializer such that[*stoppable-callback-for*](#concept:stoppable-callback-for "32.3.3Stop token concepts[stoptoken.concepts]")<CallbackFn, Token, Initializer> is satisfied,[*stoppable-callback-for*](#concept:stoppable-callback-for "32.3.3Stop token concepts[stoptoken.concepts]")<CallbackFn, Token, Initializer> is modeled[.](#7.3.sentence-1)
- [(7.4)](#7.4)
If t is disengaged,
evaluations of t.stop_possible() and t.stop_requested() are false[.](#7.4.sentence-1)
- [(7.5)](#7.5)
If t and u reference the same stop state, or
if both t and u are disengaged,t == u is true; otherwise, it is false[.](#7.5.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L741)
An object
whose type models the exposition-only [*stoppable-source*](#concept:stoppable-source "32.3.3Stop token concepts[stoptoken.concepts]") concept
can be queried
whether stop has been requested (stop_requested) and
whether stop is possible (stop_possible)[.](#8.sentence-1)
It is a factory for associated stop tokens (get_token), and
a stop request can be made on it (request_stop)[.](#8.sentence-2)
It maintains a list of registered stop callback invocations
that it executes when a stop request is first made[.](#8.sentence-3)
template<class Source>concept [*stoppable-source*](#concept:stoppable-source "32.3.3Stop token concepts[stoptoken.concepts]") = // *exposition only*requires (Source& src, const Source csrc) { // see implicit expression variations ([[concepts.equality]](concepts.equality "18.2Equality preservation")){ csrc.get_token() } -> stoppable_token; { csrc.stop_possible() } noexcept -> [same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<bool>; { csrc.stop_requested() } noexcept -> [same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<bool>; { src.request_stop() } -> [same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<bool>; };
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L762)
An object whose type models [*stoppable-source*](#concept:stoppable-source "32.3.3Stop token concepts[stoptoken.concepts]") has
at most one associated logical stop state[.](#9.sentence-1)
If it has no associated stop state, it is said to be disengaged[.](#9.sentence-2)
Let s be an object whose type models [*stoppable-source*](#concept:stoppable-source "32.3.3Stop token concepts[stoptoken.concepts]") and
that is disengaged[.](#9.sentence-3)
s.stop_possible() and s.stop_requested() shall be false[.](#9.sentence-4)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L770)
Let t be an object whose type models [*stoppable-source*](#concept:stoppable-source "32.3.3Stop token concepts[stoptoken.concepts]")[.](#10.sentence-1)
If t is disengaged,t.get_token() shall return a disengaged stop token;
otherwise, it shall return
a stop token that is associated with the stop state of t[.](#10.sentence-2)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L777)
Calls to the member functionsrequest_stop, stop_requested, and stop_possible and
similarly named member functions
on associated [stoppable_token](#concept:stoppable_token "32.3.3Stop token concepts[stoptoken.concepts]") objects
do not introduce data races[.](#11.sentence-1)
A call to request_stop that returns true synchronizes with
a call to stop_requested on
an associated[stoppable_token](#concept:stoppable_token "32.3.3Stop token concepts[stoptoken.concepts]") or [*stoppable-source*](#concept:stoppable-source "32.3.3Stop token concepts[stoptoken.concepts]") object
that returns true[.](#11.sentence-2)
Registration of a callback synchronizes with the invocation of that callback[.](#11.sentence-3)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L790)
If the [*stoppable-source*](#concept:stoppable-source "32.3.3Stop token concepts[stoptoken.concepts]") is disengaged,request_stop shall have no effect and return false[.](#12.sentence-1)
Otherwise, it shall execute a [*stop request operation*](#def:operation,stop_request "32.3.3Stop token concepts[stoptoken.concepts]") on the associated stop state[.](#12.sentence-2)
A stop request operation determines
whether the stop state has received a stop request, and
if not, makes a stop request[.](#12.sentence-3)
The determination and making of the stop request shall happen atomically,
as-if by a read-modify-write operation ([[intro.races]](intro.races "6.10.2.2Data races"))[.](#12.sentence-4)
If the request was made,
the stop state's registered callback invocations shall be
synchronously executed[.](#12.sentence-5)
If an invocation of a callback exits via an exception
then terminate shall be invoked ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#12.sentence-6)
[*Note [2](#note-2)*:
No constraint is placed on the order
in which the callback invocations are executed[.](#12.sentence-7)
— *end note*]
request_stop shall return true if a stop request was made, andfalse otherwise[.](#12.sentence-8)
After a call to request_stop either
a call to stop_possible shall return false or
a call to stop_requested shall return true[.](#12.sentence-9)
[*Note [3](#note-3)*:
A stop request includes notifying
all condition variables of type condition_variable_any temporarily registered during
an interruptible wait ([[thread.condvarany.intwait]](thread.condvarany.intwait "32.7.5.3Interruptible waits"))[.](#12.sentence-10)
— *end note*]