[thread.stoptoken] (original) (raw)

32 Concurrency support library [thread]

32.3 Stop tokens [thread.stoptoken]

32.3.1 Introduction [thread.stoptoken.intro]

Subclause [thread.stoptoken] describes components that can be used to asynchronously request that an operation stops execution in a timely manner, typically because the result is no longer required.

Such a request is called a stop request.

The conceptsstoppable-source,stoppable_token, andstoppable-callback-forspecify the required syntax and semantics of shared access to a stop state.

Any object modeling stoppable-source,stoppable_token, orstoppable-callback-forthat refers to the same stop state is an associated stoppable-source,stoppable_token, orstoppable-callback-for, respectively.

An object of a type that models stoppable_tokencan be passed to an operation that can either

A stop request made via an object whose type models stoppable-sourcewill be visible to all associated stoppable_token andstoppable-source objects.

Once a stop request has been made it cannot be withdrawn (a subsequent stop request has no effect).

Callbacks registered via an object whose type models stoppable-callback-forare called when a stop request is first made by any associated stoppable-source object.

The types stop_source and stop_token and the class template stop_callback implement the semantics of shared ownership of a stop state.

The last remaining owner of the stop state automatically releases the resources associated with the stop state.

An object of type inplace_stop_sourceis the sole owner of its stop state.

An object of type inplace_stop_token or of a specialization of the class template inplace_stop_callbackdoes not participate in ownership of its associated stop state.

[Note 1:

They are for use when all uses of the associated token and callback objects are known to nest within the lifetime of the inplace_stop_source object.

— _end note_]

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:

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:

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_]

32.3.4 Class stop_token [stoptoken]

32.3.4.1 General [stoptoken.general]

The class stop_token models the concept stoppable_token.

It shares ownership of its stop state, if any, with its associated stop_source object ([stopsource]) and any stop_token objects to which it compares equal.

namespace std { class stop_token { public: template<class CallbackFn> using callback_type = stop_callback<CallbackFn>; stop_token() noexcept = default;void swap(stop_token&) noexcept;bool stop_requested() const noexcept;bool stop_possible() const noexcept;bool operator==(const stop_token& rhs) noexcept = default;private: shared_ptr<_unspecified_> stop-state; };}

stop-state refers to the stop_token's associated stop state.

A stop_token object is disengaged when stop-state is empty.

32.3.4.2 Member functions [stoptoken.mem]

void swap(stop_token& rhs) noexcept;

Effects: Equivalent to:stop-state.swap(rhs.stop-state);

bool stop_requested() const noexcept;

Returns: true if stop-state refers to a stop state that has received a stop request; otherwise, false.

bool stop_possible() const noexcept;

Returns: false if

otherwise, true.

32.3.5 Class stop_source [stopsource]

32.3.5.1 General [stopsource.general]

namespace std { class stop_source { public: stop_source();explicit stop_source(nostopstate_t) noexcept {} void swap(stop_source&) noexcept;bool request_stop() noexcept;bool operator==(const stop_source& rhs) noexcept = default;private: shared_ptr<_unspecified_> stop-state; };}

stop-state refers to the stop_source's associated stop state.

A stop_source object is disengaged when stop-state is empty.

32.3.5.2 Constructors, copy, and assignment [stopsource.cons]

Effects: Initializes stop-state with a pointer to a new stop state.

Postconditions: stop_possible() is trueand stop_requested() is false.

Throws: bad_alloc if memory cannot be allocated for the stop state.

32.3.5.3 Member functions [stopsource.mem]

void swap(stop_source& rhs) noexcept;

Effects: Equivalent to:stop-state.swap(rhs.stop-state);

stop_token get_token() const noexcept;

Returns: stop_token() if stop_possible() is false; otherwise a new associated stop_token object; i.e., its stop-state member is equal to the stop-state member of *this.

bool stop_possible() const noexcept;

Returns: stop-state != nullptr.

bool stop_requested() const noexcept;

Returns: true if stop-state refers to a stop state that has received a stop request; otherwise, false.

bool request_stop() noexcept;

Effects: Executes a stop request operation ([stoptoken.concepts]) on the associated stop state, if any.

32.3.6 Class template stop_callback [stopcallback]

32.3.6.1 General [stopcallback.general]

namespace std { template<class CallbackFn> class stop_callback { public: using callback_type = CallbackFn;template<class Initializer> explicit stop_callback(const stop_token& st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);template<class Initializer> explicit stop_callback(stop_token&& st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);~stop_callback(); stop_callback(const stop_callback&) = delete; stop_callback(stop_callback&&) = delete; stop_callback& operator=(const stop_callback&) = delete; stop_callback& operator=(stop_callback&&) = delete;private: CallbackFn callback-fn; };template<class CallbackFn> stop_callback(stop_token, CallbackFn) -> stop_callback<CallbackFn>;}

Mandates: stop_callback is instantiated with an argument for the template parameter CallbackFnthat satisfies both invocableand destructible.

Remarks: For a type Initializer, ifstoppable-callback-for<CallbackFn, stop_token, Initializer>is satisfied, thenstoppable-callback-for<CallbackFn, stop_token, Initializer> is modeled.

The exposition-only callback-fn member is the associated callback function ([stoptoken.concepts]) ofstop_callback<
CallbackFn> objects.

32.3.6.2 Constructors and destructor [stopcallback.cons]

template<class Initializer> explicit stop_callback(const stop_token& st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);template<class Initializer> explicit stop_callback(stop_token&& st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);

Constraints: CallbackFn and Initializer satisfyconstructible_from<CallbackFn, Initializer>.

Effects: Initializes callback-fn with std​::​forward<Initializer>(init)and executes a stoppable callback registration ([stoptoken.concepts]).

If a callback is registered with st's shared stop state, then *this acquires shared ownership of that stop state.

Effects: Executes a stoppable callback deregistration ([stoptoken.concepts]) and releases ownership of the stop state, if any.

32.3.7 Class never_stop_token [stoptoken.never]

The class never_stop_token models the unstoppable_token concept.

It provides a stop token interface, but also provides static information that a stop is never possible nor requested.

namespace std { class never_stop_token { struct callback-type { explicit callback-type(never_stop_token, auto&&) noexcept {} };public: template<class> using callback_type = callback-type;static constexpr bool stop_requested() noexcept { return false; } static constexpr bool stop_possible() noexcept { return false; } bool operator==(const never_stop_token&) const = default;};}

32.3.8 Class inplace_stop_token [stoptoken.inplace]

32.3.8.1 General [stoptoken.inplace.general]

The class inplace_stop_token models the concept stoppable_token.

It references the stop state of its associated inplace_stop_source object ([stopsource.inplace]), if any.

namespace std { class inplace_stop_token { public: template<class CallbackFn> using callback_type = inplace_stop_callback<CallbackFn>; inplace_stop_token() = default;bool operator==(const inplace_stop_token&) const = default;bool stop_requested() const noexcept;bool stop_possible() const noexcept;void swap(inplace_stop_token&) noexcept;private: const inplace_stop_source* stop-source = nullptr; };}

32.3.8.2 Member functions [stoptoken.inplace.mem]

void swap(inplace_stop_token& rhs) noexcept;

Effects: Exchanges the values of stop-source and rhs.stop-source.

bool stop_requested() const noexcept;

Effects: Equivalent to:return stop-source != nullptr && _stop-source_->stop_requested();

[Note 1:

As specified in [basic.life], the behavior of stop_requested is undefined unless the call strongly happens before the start of the destructor of the associated inplace_stop_source object, if any.

— _end note_]

stop_possible() const noexcept;

Returns: stop-source != nullptr.

[Note 2:

As specified in [basic.stc.general], the behavior of stop_possible is implementation-defined unless the call strongly happens before the end of the storage duration of the associated inplace_stop_source object, if any.

— _end note_]

32.3.9 Class inplace_stop_source [stopsource.inplace]

32.3.9.1 General [stopsource.inplace.general]

The class inplace_stop_source models stoppable-source.

namespace std { class inplace_stop_source { public: constexpr inplace_stop_source() noexcept; inplace_stop_source(inplace_stop_source&&) = delete; inplace_stop_source(const inplace_stop_source&) = delete; inplace_stop_source& operator=(inplace_stop_source&&) = delete; inplace_stop_source& operator=(const inplace_stop_source&) = delete;~inplace_stop_source();constexpr inplace_stop_token get_token() const noexcept;static constexpr bool stop_possible() noexcept { return true; } bool stop_requested() const noexcept;bool request_stop() noexcept;};}

32.3.9.2 Constructors [stopsource.inplace.cons]

constexpr inplace_stop_source() noexcept;

Effects: Initializes a new stop state inside *this.

Postconditions: stop_requested() is false.

32.3.9.3 Member functions [stopsource.inplace.mem]

constexpr inplace_stop_token get_token() const noexcept;

Returns: A new associated inplace_stop_token object whose stop-source member is equal to this.

bool stop_requested() const noexcept;

Returns: true if the stop state inside *thishas received a stop request; otherwise, false.

bool request_stop() noexcept;

Effects: Executes a stop request operation ([stoptoken.concepts]).

Postconditions: stop_requested() is true.

32.3.10 Class template inplace_stop_callback [stopcallback.inplace]

32.3.10.1 General [stopcallback.inplace.general]

namespace std { template<class CallbackFn> class inplace_stop_callback { public: using callback_type = CallbackFn;template<class Initializer> explicit inplace_stop_callback(inplace_stop_token st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);~inplace_stop_callback(); inplace_stop_callback(inplace_stop_callback&&) = delete; inplace_stop_callback(const inplace_stop_callback&) = delete; inplace_stop_callback& operator=(inplace_stop_callback&&) = delete; inplace_stop_callback& operator=(const inplace_stop_callback&) = delete;private: CallbackFn callback-fn; };template<class CallbackFn> inplace_stop_callback(inplace_stop_token, CallbackFn) -> inplace_stop_callback<CallbackFn>;}

Remarks: For a type Initializer, ifstoppable-callback-for<CallbackFn, inplace_stop_token, Initializer> is satisfied, thenstoppable-callback-for<CallbackFn, inplace_stop_token, Initializer> is modeled.

For an inplace_stop_callback<CallbackFn> object, the exposition-only callback-fn member is its associated callback function ([stoptoken.concepts]).

32.3.10.2 Constructors and destructor [stopcallback.inplace.cons]

template<class Initializer> explicit inplace_stop_callback(inplace_stop_token st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);

Effects: Initializes callback-fn with std​::​forward<Initializer>(init)and executes a stoppable callback registration ([stoptoken.concepts]).

~inplace_stop_callback();

Effects: Executes a stoppable callback deregistration ([stoptoken.concepts]).