Init
This commit is contained in:
293
cppdraft/stoptoken/concepts.md
Normal file
293
cppdraft/stoptoken/concepts.md
Normal file
@@ -0,0 +1,293 @@
|
||||
[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.3 Stop 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.3 Stop token concepts [stoptoken.concepts]") = // *exposition only*[invocable](concept.invocable#concept:invocable "18.7.2 Concept invocable [concept.invocable]")<CallbackFn> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<CallbackFn, Initializer> &&requires { typename stop_callback_for_t<Token, CallbackFn>; } &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept 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.2 Concept 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.3 Stop 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.11 Concept constructible_from [concept.constructible]")<SCB, Token, Initializer>
|
||||
|
||||
* [(3.1.2)](#3.1.2)
|
||||
|
||||
[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<SCB, Token&, Initializer>
|
||||
|
||||
* [(3.1.3)](#3.1.3)
|
||||
|
||||
[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept 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.3 Stop 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.3 Stop 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.6 block"))
|
||||
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.2 Data 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.3 Stop 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.3 Stop token concepts [stoptoken.concepts]") concept checks
|
||||
for a [stoppable_token](#concept:stoppable_token "32.3.3 Stop 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.3 Stop 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.2 Concept same_as [concept.same]")<bool>; { tok.stop_possible() } noexcept -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool>; { Token(tok) } noexcept; // see implicit expression variations ([[concepts.equality]](concepts.equality "18.2 Equality preservation"))} &&[copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<Token> &&[equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<Token>;
|
||||
|
||||
template<class Token>concept [unstoppable_token](#concept:unstoppable_token "32.3.3 Stop token concepts [stoptoken.concepts]") =[stoppable_token](#concept:stoppable_token "32.3.3 Stop 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.3 Stop token concepts [stoptoken.concepts]") has at most one associated logical stop state[.](#5.sentence-1)
|
||||
|
||||
A [stoppable_token](#concept:stoppable_token "32.3.3 Stop token concepts [stoptoken.concepts]") object with no associated stop state
|
||||
is said to be [*disengaged*](#def:disengaged "32.3.3 Stop 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.3 Stop 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.2 Data 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.3 Stop token concepts [stoptoken.concepts]")<CallbackFn, Token, Initializer> is satisfied,[*stoppable-callback-for*](#concept:stoppable-callback-for "32.3.3 Stop 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.3 Stop 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.3 Stop token concepts [stoptoken.concepts]") = // *exposition only*requires (Source& src, const Source csrc) { // see implicit expression variations ([[concepts.equality]](concepts.equality "18.2 Equality preservation")){ csrc.get_token() } -> stoppable_token; { csrc.stop_possible() } noexcept -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool>; { csrc.stop_requested() } noexcept -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool>; { src.request_stop() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept 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.3 Stop 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.3 Stop 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.3 Stop 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.3 Stop 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.3 Stop token concepts [stoptoken.concepts]") or [*stoppable-source*](#concept:stoppable-source "32.3.3 Stop 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.3 Stop 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.3 Stop 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.2 Data 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.2 The 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.3 Interruptible waits"))[.](#12.sentence-10)
|
||||
|
||||
â *end note*]
|
||||
Reference in New Issue
Block a user