32 Thread support library [thread]

32.4 Threads [thread.threads]

32.4.4 Class jthread [thread.jthread.class]

32.4.4.1 General [thread.jthread.class.general]

The class jthread provides a mechanism to create a new thread of execution.
The functionality is the same as for class thread ([thread.thread.class]) with the additional abilities to provide a stop_­token ([thread.stoptoken]) to the new thread of execution, make stop requests, and automatically join.
namespace std { class jthread { public: // types using id = thread::id; using native_handle_type = thread::native_handle_type; // [thread.jthread.cons], constructors, move, and assignment jthread() noexcept; template<class F, class... Args> explicit jthread(F&& f, Args&&... args); ~jthread(); jthread(const jthread&) = delete; jthread(jthread&&) noexcept; jthread& operator=(const jthread&) = delete; jthread& operator=(jthread&&) noexcept; // [thread.jthread.mem], members void swap(jthread&) noexcept; [[nodiscard]] bool joinable() const noexcept; void join(); void detach(); [[nodiscard]] id get_id() const noexcept; [[nodiscard]] native_handle_type native_handle(); // see [thread.req.native] // [thread.jthread.stop], stop token handling [[nodiscard]] stop_source get_stop_source() noexcept; [[nodiscard]] stop_token get_stop_token() const noexcept; bool request_stop() noexcept; // [thread.jthread.special], specialized algorithms friend void swap(jthread& lhs, jthread& rhs) noexcept; // [thread.jthread.static], static members [[nodiscard]] static unsigned int hardware_concurrency() noexcept; private: stop_source ssource; // exposition only }; }

32.4.4.2 Constructors, move, and assignment [thread.jthread.cons]

jthread() noexcept;
Effects: Constructs a jthread object that does not represent a thread of execution.
Postconditions: get_­id() == id() is true and ssource.stop_­possible() is false.
template<class F, class... Args> explicit jthread(F&& f, Args&&... args);
Constraints: remove_­cvref_­t<F> is not the same type as jthread.
Mandates: The following are all true:
  • is_­constructible_­v<decay_­t<F>, F>,
  • (is_­constructible_­v<decay_­t<Args>, Args> && ...),
  • is_­move_­constructible_­v<decay_­t<F>>,
  • (is_­move_­constructible_­v<decay_­t<Args>> && ...), and
  • is_­invocable_­v<decay_­t<F>, decay_­t<Args>...> ||
    is_­invocable_­v<decay_­t<F>, stop_­token, decay_­t<Args>...>.
Preconditions: decay_­t<F> and each type in decay_­t<Args> meet the Cpp17MoveConstructible requirements.
Effects: Initializes ssource.
The new thread of execution executes invoke(decay-copy(std::forward<F>(f)), get_stop_token(), decay-copy(std::forward<Args>(args))...) if that expression is well-formed, otherwise invoke(decay-copy(std::forward<F>(f)), decay-copy(std::forward<Args>(args))...) with the calls to decay-copy being evaluated in the constructing thread.
Any return value from this invocation is ignored.
[Note 1:
This implies that any exceptions not thrown from the invocation of the copy of f will be thrown in the constructing thread, not the new thread.
— end note]
If the invoke expression exits via an exception, terminate is called.
Synchronization: The completion of the invocation of the constructor synchronizes with the beginning of the invocation of the copy of f.
Postconditions: get_­id() != id() is true and ssource.stop_­possible() is true and *this represents the newly started thread.
[Note 2:
The calling thread can make a stop request only once, because it cannot replace this stop token.
— end note]
Throws: system_­error if unable to start the new thread.
Error conditions:
  • resource_­unavailable_­try_­again — the system lacked the necessary resources to create another thread, or the system-imposed limit on the number of threads in a process would be exceeded.
jthread(jthread&& x) noexcept;
Postconditions: x.get_­id() == id() and get_­id() returns the value of x.get_­id() prior to the start of construction.
ssource has the value of x.ssource prior to the start of construction and x.ssource.stop_­possible() is false.
~jthread();
Effects: If joinable() is true, calls request_­stop() and then join().
[Note 3:
Operations on *this are not synchronized.
— end note]
jthread& operator=(jthread&& x) noexcept;
Effects: If joinable() is true, calls request_­stop() and then join().
Assigns the state of x to *this and sets x to a default constructed state.
Postconditions: x.get_­id() == id() and get_­id() returns the value of x.get_­id() prior to the assignment.
ssource has the value of x.ssource prior to the assignment and x.ssource.stop_­possible() is false.
Returns: *this.

32.4.4.3 Members [thread.jthread.mem]

void swap(jthread& x) noexcept;
Effects: Exchanges the values of *this and x.
[[nodiscard]] bool joinable() const noexcept;
Returns: get_­id() != id().
void join();
Effects: Blocks until the thread represented by *this has completed.
Synchronization: The completion of the thread represented by *this synchronizes with ([intro.multithread]) the corresponding successful join() return.
[Note 1:
Operations on *this are not synchronized.
— end note]
Postconditions: The thread represented by *this has completed.
get_­id() == id().
Throws: system_­error when an exception is required ([thread.req.exception]).
Error conditions:
  • resource_­deadlock_­would_­occur — if deadlock is detected or get_­id() == this_­thread​::​​get_­id().
  • no_­such_­process — if the thread is not valid.
  • invalid_­argument — if the thread is not joinable.
void detach();
Effects: The thread represented by *this continues execution without the calling thread blocking.
When detach() returns, *this no longer represents the possibly continuing thread of execution.
When the thread previously represented by *this ends execution, the implementation releases any owned resources.
Postconditions: get_­id() == id().
Throws: system_­error when an exception is required ([thread.req.exception]).
Error conditions:
  • no_­such_­process — if the thread is not valid.
  • invalid_­argument — if the thread is not joinable.
id get_id() const noexcept;
Returns: A default constructed id object if *this does not represent a thread, otherwise this_­thread​::​get_­id() for the thread of execution represented by *this.

32.4.4.4 Stop token handling [thread.jthread.stop]

[[nodiscard]] stop_source get_stop_source() noexcept;
Effects: Equivalent to: return ssource;
[[nodiscard]] stop_token get_stop_token() const noexcept;
Effects: Equivalent to: return ssource.get_­token();
bool request_stop() noexcept;
Effects: Equivalent to: return ssource.request_­stop();

32.4.4.5 Specialized algorithms [thread.jthread.special]

friend void swap(jthread& x, jthread& y) noexcept;
Effects: Equivalent to: x.swap(y).

32.4.4.6 Static members [thread.jthread.static]

[[nodiscard]] static unsigned int hardware_concurrency() noexcept;
Returns: thread​::​hardware_­concurrency().