[stoptoken.concepts] (original) (raw)
32 Concurrency support library [thread]
32.3 Stop tokens [thread.stoptoken]
32.3.3 Stop token concepts [stoptoken.concepts]
The exposition-only stoppable-callback-for concept checks for a callback compatible with a given Token type.
template<class CallbackFn, class Token, class Initializer = CallbackFn> concept stoppable-callback-for = invocable<CallbackFn> && constructible_from<CallbackFn, Initializer> && requires { typename stop_callback_for_t<Token, CallbackFn>; } && constructible_from<stop_callback_for_t<Token, CallbackFn>, const Token&, Initializer>;
Let t and u be distinct, valid objects of type Tokenthat reference the same logical stop state; let init be an expression such thatsame_as<decltype(init), Initializer> is true; and let SCB denote the type stop_callback_for_t<Token, CallbackFn>.
The conceptstoppable-callback-for<CallbackFn, Token, Initializer>is modeled only if:
- An object of type SCB has an associated callback function of type CallbackFn.
Let scb be an object of type SCB and let callback_fn denote scb's associated callback function.
Direct-non-list-initializing scb from arguments t and initshall execute a stoppable callback registration as follows:- If t.stop_possible() is true:
* callback_fn shall be direct-initialized with init.
* Construction of scb shall only throw exceptions thrown by the initialization of callback_fn from init.
* The callback invocation std::forward<CallbackFn>(callback_fn)()shall be registered with t's associated stop state as follows:
* If t.stop_requested() evaluates to falseat 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.
* 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.
If the callback invocation was added to stop state's list of callbacks,scb shall be associated with the stop state. - [Note 1:
If t.stop_possible() is false, there is no requirement that the initialization of scbcauses the initialization of callback_fn.
— _end note_]
- If t.stop_possible() is true:
- Destruction of scb shall execute a stoppable callback deregistration as follows (in order):
- 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.
- Otherwise, the invocation of callback_fn shall be removed from the associated stop state.
- If callback_fn is concurrently executing on another thread, then the stoppable callback deregistration shall block ([defns.block]) until the invocation of callback_fn returns such that the return from the invocation of callback_fnstrongly happens before ([intro.races]) the destruction of callback_fn.
- 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.
- A stoppable callback deregistration shall not block on the completion of the invocation of some other callback registered with the same logical stop state.
- The stoppable callback deregistration shall destroy callback_fn.
The stoppable_token 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.
The unstoppable_token concept checks for a stoppable_token type that does not allow stopping.
template<template<class> class> struct check-type-alias-exists; template<class Token> concept stoppable_token = requires (const Token tok) { typename check-type-alias-exists<Token::template callback_type>;{ tok.stop_requested() } noexcept -> same_as<bool>;{ tok.stop_possible() } noexcept -> same_as<bool>;{ Token(tok) } noexcept; } && copyable<Token> && equality_comparable<Token>;template<class Token> concept unstoppable_token = stoppable_token<Token> && requires (const Token tok) { requires bool_constant<(!tok.stop_possible())>::value;};
An object whose type models stoppable_tokenhas at most one associated logical stop state.
A stoppable_token object with no associated stop state is said to be disengaged.
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.
The type Token models stoppable_token only if:
- Any evaluation of u.stop_possible() or u.stop_requested()that happens after ([intro.races]) SP is false.
- Any evaluation of u.stop_possible() or u.stop_requested()that happens after SR is true.
- For any types CallbackFn and Initializer such thatstoppable-callback-for<CallbackFn, Token, Initializer>is satisfied,stoppable-callback-for<CallbackFn, Token, Initializer>is modeled.
- If t is disengaged, evaluations of t.stop_possible() and t.stop_requested()are false.
- 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.
An object whose type models the exposition-only stoppable-source concept can be queried whether stop has been requested (stop_requested) and whether stop is possible (stop_possible).
It is a factory for associated stop tokens (get_token), and a stop request can be made on it (request_stop).
It maintains a list of registered stop callback invocations that it executes when a stop request is first made.
template<class Source> concept stoppable-source = requires (Source& src, const Source csrc) { { csrc.get_token() } -> stoppable_token;{ csrc.stop_possible() } noexcept -> same_as<bool>;{ csrc.stop_requested() } noexcept -> same_as<bool>;{ src.request_stop() } -> same_as<bool>;};
An object whose type models stoppable-source has at most one associated logical stop state.
If it has no associated stop state, it is said to be disengaged.
Let s be an object whose type models stoppable-source and that is disengaged.
s.stop_possible() and s.stop_requested() shall be false.
Let t be an object whose type models stoppable-source.
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.
Calls to the member functionsrequest_stop, stop_requested, and stop_possible and similarly named member functions on associated stoppable_token objects do not introduce data races.
A call to request_stop that returns true synchronizes with a call to stop_requested on an associatedstoppable_token or stoppable-source object that returns true.
Registration of a callback synchronizes with the invocation of that callback.
If the stoppable-source is disengaged,request_stop shall have no effect and return false.
Otherwise, it shall execute a stop request operationon the associated stop state.
A stop request operation determines whether the stop state has received a stop request, and if not, makes a stop request.
The determination and making of the stop request shall happen atomically, as-if by a read-modify-write operation ([intro.races]).
If the request was made, the stop state's registered callback invocations shall be synchronously executed.
If an invocation of a callback exits via an exception then terminate shall be invoked ([except.terminate]).
[Note 2:
No constraint is placed on the order in which the callback invocations are executed.
— _end note_]
request_stop shall return true if a stop request was made, andfalse otherwise.
After a call to request_stop either a call to stop_possible shall return false or a call to stop_requested shall return true.
[Note 3:
A stop request includes notifying all condition variables of type condition_variable_anytemporarily registered during an interruptible wait ([thread.condvarany.intwait]).
— _end note_]