[thread.stoptoken] (original) (raw)
32 Thread 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 asynchonously 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.
stop_source, stop_token, and stop_callbackimplement semantics of shared ownership of a stop state.
Any stop_source, stop_token, or stop_callbackthat shares ownership of the same stop state is an associated stop_source, stop_token, or stop_callback, respectively.
The last remaining owner of the stop state automatically releases the resources associated with the stop state.
A stop_token can be passed to an operation which can either
- actively poll the token to check if there has been a stop request, or
- register a callback using the stop_callback class template which will be called in the event that a stop request is made.
A stop request made via a stop_source will be visible to all associated stop_token and stop_source objects.
Once a stop request has been made it cannot be withdrawn (a subsequent stop request has no effect).
Callbacks registered via a stop_callback object are called when a stop request is first made by any associated stop_source object.
Calls to the functions request_stop, stop_requested, and stop_possibledo not introduce data races.
A call to request_stop that returns truesynchronizes with a call to stop_requestedon an associated stop_token or stop_source object that returns true.
Registration of a callback synchronizes with the invocation of that callback.
32.3.3 Class stop_token [stoptoken]
32.3.3.1 General [stoptoken.general]
The class stop_token provides an interface for querying whether a stop request has been made (stop_requested) or can ever be made (stop_possible) using an associated stop_source object ([stopsource]).
A stop_token can also be passed to astop_callback ([stopcallback]) constructor to register a callback to be called when a stop request has been made from an associated stop_source.
namespace std { class stop_token { public: stop_token() noexcept; stop_token(const stop_token&) noexcept; stop_token(stop_token&&) noexcept; stop_token& operator=(const stop_token&) noexcept; stop_token& operator=(stop_token&&) noexcept;~stop_token();void swap(stop_token&) noexcept;[[nodiscard]] bool stop_requested() const noexcept;[[nodiscard]] bool stop_possible() const noexcept;[[nodiscard]] friend bool operator==(const stop_token& lhs, const stop_token& rhs) noexcept;friend void swap(stop_token& lhs, stop_token& rhs) noexcept;};}
32.3.3.2 Constructors, copy, and assignment [stoptoken.cons]
Postconditions: stop_possible() is false andstop_requested() is false.
[Note 1:
Because the created stop_token object can never receive a stop request, no resources are allocated for a stop state.
— _end note_]
stop_token(const stop_token& rhs) noexcept;
Postconditions: *this == rhs is true.
[Note 2:
*this and rhs share the ownership of the same stop state, if any.
— _end note_]
stop_token(stop_token&& rhs) noexcept;
Postconditions: *this contains the value of rhsprior to the start of construction and rhs.stop_possible() is false.
Effects: Releases ownership of the stop state, if any.
stop_token& operator=(const stop_token& rhs) noexcept;
Effects: Equivalent to: stop_token(rhs).swap(*this).
stop_token& operator=(stop_token&& rhs) noexcept;
Effects: Equivalent to: stop_token(std::move(rhs)).swap(*this).
void swap(stop_token& rhs) noexcept;
Effects: Exchanges the values of *this and rhs.
32.3.3.3 Members [stoptoken.mem]
[[nodiscard]] bool stop_requested() const noexcept;
Returns: true if *this has ownership of a stop state that has received a stop request; otherwise, false.
[[nodiscard]] bool stop_possible() const noexcept;
Returns: false if:
- *this does not have ownership of a stop state, or
- a stop request was not made and there are no associated stop_source objects;
otherwise, true.
32.3.3.4 Non-member functions [stoptoken.nonmembers]
[[nodiscard]] bool operator==(const stop_token& lhs, const stop_token& rhs) noexcept;
Returns: true if lhs and rhs have ownership of the same stop state or if both lhs and rhs do not have ownership of a stop state; otherwise false.
friend void swap(stop_token& x, stop_token& y) noexcept;
Effects: Equivalent to: x.swap(y).
32.3.4 Class stop_source [stopsource]
32.3.4.1 General [stopsource.general]
The class stop_source implements the semantics of making a stop request.
A stop request made on a stop_source object is visible to all associated stop_source and stop_token ([stoptoken]) objects.
Once a stop request has been made it cannot be withdrawn (a subsequent stop request has no effect).
namespace std { struct nostopstate_t { explicit nostopstate_t() = default;};inline constexpr nostopstate_t nostopstate{};class stop_source { public: stop_source();explicit stop_source(nostopstate_t) noexcept; stop_source(const stop_source&) noexcept; stop_source(stop_source&&) noexcept; stop_source& operator=(const stop_source&) noexcept; stop_source& operator=(stop_source&&) noexcept;~stop_source();void swap(stop_source&) noexcept;[[nodiscard]] stop_token get_token() const noexcept;[[nodiscard]] bool stop_possible() const noexcept;[[nodiscard]] bool stop_requested() const noexcept;bool request_stop() noexcept;[[nodiscard]] friend bool operator==(const stop_source& lhs, const stop_source& rhs) noexcept;friend void swap(stop_source& lhs, stop_source& rhs) noexcept;};}
32.3.4.2 Constructors, copy, and assignment [stopsource.cons]
Effects: Initialises *this to have ownership of a new stop state.
Postconditions: stop_possible() is trueand stop_requested() is false.
Throws: bad_alloc if memory could not be allocated for the stop state.
explicit stop_source(nostopstate_t) noexcept;
Postconditions: stop_possible() is false andstop_requested() is false.
[Note 1:
No resources are allocated for the state.
— _end note_]
stop_source(const stop_source& rhs) noexcept;
Postconditions: *this == rhs is true.
[Note 2:
*this and rhs share the ownership of the same stop state, if any.
— _end note_]
stop_source(stop_source&& rhs) noexcept;
Postconditions: *this contains the value of rhsprior to the start of construction and rhs.stop_possible() is false.
Effects: Releases ownership of the stop state, if any.
stop_source& operator=(const stop_source& rhs) noexcept;
Effects: Equivalent to: stop_source(rhs).swap(*this).
stop_source& operator=(stop_source&& rhs) noexcept;
Effects: Equivalent to: stop_source(std::move(rhs)).swap(*this).
void swap(stop_source& rhs) noexcept;
Effects: Exchanges the values of *this and rhs.
32.3.4.3 Members [stopsource.mem]
[[nodiscard]] stop_token get_token() const noexcept;
Returns: stop_token() if stop_possible() is false; otherwise a new associated stop_token object.
[[nodiscard]] bool stop_possible() const noexcept;
Returns: true if *this has ownership of a stop state; otherwise, false.
[[nodiscard]] bool stop_requested() const noexcept;
Returns: true if *this has ownership of a stop state that has received a stop request; otherwise, false.
bool request_stop() noexcept;
Effects: If *this does not have ownership of a stop state, returns false.
Otherwise, atomically determines whether the owned stop state has received a stop request, and if not, makes a stop request.
The determination and making of the stop request are an atomic read-modify-write operation ([intro.races]).
If the request was made, the callbacks registered by associated stop_callback objects are synchronously called.
If an invocation of a callback exits via an exception then terminate is called ([except.terminate]).
[Note 1:
A stop request includes notifying all condition variables of type condition_variable_anytemporarily registered during an interruptible wait ([thread.condvarany.intwait]).
— _end note_]
Postconditions: stop_possible() is falseor stop_requested() is true.
Returns: true if this call made a stop request; otherwise false.
32.3.4.4 Non-member functions [stopsource.nonmembers]
[[nodiscard]] friend bool operator==(const stop_source& lhs, const stop_source& rhs) noexcept;
Returns: true if lhs and rhs have ownership of the same stop state or if both lhs and rhs do not have ownership of a stop state; otherwise false.
friend void swap(stop_source& x, stop_source& y) noexcept;
Effects: Equivalent to: x.swap(y).
32.3.5 Class template stop_callback [stopcallback]
32.3.5.1 General [stopcallback.general]
namespace std { template<class Callback> class stop_callback { public: using callback_type = Callback;template<class C> explicit stop_callback(const stop_token& st, C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>);template<class C> explicit stop_callback(stop_token&& st, C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>);~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: Callback callback; };template<class Callback> stop_callback(stop_token, Callback) -> stop_callback<Callback>;}
Mandates: stop_callback is instantiated with an argument for the template parameter Callbackthat satisfies both invocableand destructible.
Preconditions: stop_callback is instantiated with an argument for the template parameter Callbackthat models both invocableand destructible.
32.3.5.2 Constructors and destructor [stopcallback.cons]
template<class C> explicit stop_callback(const stop_token& st, C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>);template<class C> explicit stop_callback(stop_token&& st, C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>);
Effects: Initializes callback with std::forward<C>(cb).
If st.stop_requested() is true, thenstd::forward<Callback>(callback)()is evaluated in the current thread before the constructor returns.
Otherwise, if st has ownership of a stop state, acquires shared ownership of that stop state and registers the callback with that stop state such that std::forward<Callback>(callback)()is evaluated by the first call to request_stop()on an associated stop_source.
Throws: Any exception thrown by the initialization of callback.
Remarks: If evaluatingstd::forward<Callback>(callback)()exits via an exception, then terminate is called ([except.terminate]).
Effects: Unregisters the callback from the owned stop state, if any.
The destructor does not block waiting for the execution of another callback registered by an associated stop_callback.
If callback is concurrently executing on another thread, then the return from the invocation of callbackstrongly happens before ([intro.races])callback is destroyed.
If callback is executing on the current thread, then the destructor does not block ([defns.block]) waiting for the return from the invocation of callback.
Releases ownership of the stop state, if any.