Files
2025-10-25 03:02:53 +03:00

1050 lines
40 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[thread.threads]
# 32 Concurrency support library [[thread]](./#thread)
## 32.4 Threads [thread.threads]
### [32.4.1](#general) General [[thread.threads.general]](thread.threads.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1405)
[thread.threads] describes components that can be used to create and manage threads[.](#general-1.sentence-1)
[*Note [1](#general-note-1)*:
These threads are intended to map one-to-one with operating system threads[.](#general-1.sentence-2)
— *end note*]
### [32.4.2](#thread.syn) Header <thread> synopsis [[thread.syn]](thread.syn)
[🔗](#header:%3cthread%3e)
#include <compare> // see [[compare.syn]](compare.syn "17.12.1Header <compare> synopsis")namespace std {// [[thread.thread.class]](#thread.thread.class "32.4.3Class thread"), class threadclass thread; void swap(thread& x, thread& y) noexcept; // [[thread.jthread.class]](#thread.jthread.class "32.4.4Class jthread"), class jthreadclass jthread; // [[thread.thread.this]](#thread.thread.this "32.4.5Namespace this_­thread"), namespace this_threadnamespace this_thread { thread::id get_id() noexcept; void yield() noexcept; template<class Clock, class Duration>void sleep_until(const chrono::time_point<Clock, Duration>& abs_time); template<class Rep, class Period>void sleep_for(const chrono::duration<Rep, Period>& rel_time); }}
### [32.4.3](#thread.thread.class) Class thread [[thread.thread.class]](thread.thread.class)
#### [32.4.3.1](#thread.thread.class.general) General [[thread.thread.class.general]](thread.thread.class.general)
[1](#thread.thread.class.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1443)
The class thread provides a mechanism to create a new thread of execution, to join with
a thread (i.e., wait for a thread to complete), and to perform other operations that manage and
query the state of a thread[.](#thread.thread.class.general-1.sentence-1)
A thread object uniquely represents a particular thread of
execution[.](#thread.thread.class.general-1.sentence-2)
That representation may be transferred to other thread objects in such a way
that no two thread objects simultaneously represent the same thread of execution[.](#thread.thread.class.general-1.sentence-3)
A
thread of execution is [*detached*](#def:detached) when no thread object represents that thread[.](#thread.thread.class.general-1.sentence-4)
Objects of class thread can be in a state that does not represent a thread of
execution[.](#thread.thread.class.general-1.sentence-5)
[*Note [1](#thread.thread.class.general-note-1)*:
A thread object does not represent a thread of execution after
default construction, after being moved from, or after a successful call to detach orjoin[.](#thread.thread.class.general-1.sentence-6)
— *end note*]
[🔗](#lib:thread)
namespace std {class thread {public:// [[thread.thread.id]](#thread.thread.id "32.4.3.2Class thread::id"), class thread::idclass id; using native_handle_type = *implementation-defined*; // see [[thread.req.native]](thread.req.native "32.2.3Native handles")// construct/copy/destroy thread() noexcept; template<class F, class... Args> explicit thread(F&& f, Args&&... args); ~thread();
thread(const thread&) = delete;
thread(thread&&) noexcept;
thread& operator=(const thread&) = delete;
thread& operator=(thread&&) noexcept; // [[thread.thread.member]](#thread.thread.member "32.4.3.6Members"), membersvoid swap(thread&) noexcept; bool joinable() const noexcept; void join(); void detach();
id get_id() const noexcept;
native_handle_type native_handle(); // see [[thread.req.native]](thread.req.native "32.2.3Native handles")// static membersstatic unsigned int hardware_concurrency() noexcept; };}
#### [32.4.3.2](#thread.thread.id) Class thread::id [[thread.thread.id]](thread.thread.id)
[🔗](#lib:thread::id)
namespace std {class thread::id {public: id() noexcept; }; bool operator==(thread::id x, thread::id y) noexcept;
strong_ordering operator<=>(thread::id x, thread::id y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>&operator<<(basic_ostream<charT, traits>& out, thread::id id); template<class charT> struct formatter<thread::id, charT>; // hash supporttemplate<class T> struct hash; template<> struct hash<thread::id>;}
[1](#thread.thread.id-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1516)
An object of type thread::id provides a unique identifier for
each thread of execution and a single distinct value for all thread objects that do not represent a thread of
execution ([[thread.thread.class]](#thread.thread.class "32.4.3Class thread"))[.](#thread.thread.id-1.sentence-1)
Each thread of execution has an
associated thread::id object that is not equal to thethread::id object of any other thread of execution and that is not
equal to the thread::id object of any thread object that
does not represent threads of execution[.](#thread.thread.id-1.sentence-2)
[2](#thread.thread.id-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1526)
The [*text representation*](#def:text_representation "32.4.3.2Class thread::id[thread.thread.id]") for
the character type charT of an object of type thread::id is an unspecified sequence of charT such that,
for two objects of type thread::id x and y,
if x == y is true,
the thread::id objects have the same text representation, and
if x != y is true,
the thread::id objects have distinct text representations[.](#thread.thread.id-2.sentence-1)
[3](#thread.thread.id-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1536)
thread::id is a trivially copyable class ([[class.prop]](class.prop "11.2Properties of classes"))[.](#thread.thread.id-3.sentence-1)
The library may reuse the value of a thread::id of a terminated thread that can no longer be joined[.](#thread.thread.id-3.sentence-2)
[4](#thread.thread.id-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1540)
[*Note [1](#thread.thread.id-note-1)*:
Relational operators allow thread::id objects to be used as
keys in associative containers[.](#thread.thread.id-4.sentence-1)
— *end note*]
[🔗](#lib:thread::id,constructor)
`id() noexcept;
`
[5](#thread.thread.id-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1552)
*Postconditions*: The constructed object does not represent a thread of execution[.](#thread.thread.id-5.sentence-1)
[🔗](#lib:operator==,thread::id)
`bool operator==(thread::id x, thread::id y) noexcept;
`
[6](#thread.thread.id-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1563)
*Returns*: true only if x and y represent the same
thread of execution or neither x nor y represents a thread of
execution[.](#thread.thread.id-6.sentence-1)
[🔗](#lib:operator%3c=%3e,thread::id)
`strong_ordering operator<=>(thread::id x, thread::id y) noexcept;
`
[7](#thread.thread.id-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1576)
Let P(x, y) be
an unspecified total ordering over thread::id as described in [[alg.sorting]](alg.sorting "26.8Sorting and related operations")[.](#thread.thread.id-7.sentence-1)
[8](#thread.thread.id-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1581)
*Returns*: strong_ordering::less if P(x, y) is true[.](#thread.thread.id-8.sentence-1)
Otherwise, strong_ordering::greater if P(y, x) is true[.](#thread.thread.id-8.sentence-2)
Otherwise, strong_ordering::equal[.](#thread.thread.id-8.sentence-3)
[🔗](#lib:operator%3c%3c,thread::id)
`template<class charT, class traits>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& out, thread::id id);
`
[9](#thread.thread.id-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1597)
*Effects*: Inserts the text representation for charT of id intoout[.](#thread.thread.id-9.sentence-1)
[10](#thread.thread.id-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1602)
*Returns*: out[.](#thread.thread.id-10.sentence-1)
[🔗](#lib:formatter,specializations,thread::id)
`template<class charT> struct formatter<thread::id, charT>;
`
[11](#thread.thread.id-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1613)
formatter<thread::id, charT> interprets *format-spec* as a *thread-id-format-spec*[.](#thread.thread.id-11.sentence-1)
The syntax of format specifications is as follows:
thread-id-format-spec :
fill-and-alignopt widthopt
[*Note [2](#thread.thread.id-note-2)*:
The productions *fill-and-align* and *width* are described in [[format.string.std]](format.string.std "28.5.2.2Standard format specifiers")[.](#thread.thread.id-11.sentence-3)
— *end note*]
[12](#thread.thread.id-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1628)
If the *align* option is omitted it defaults to >[.](#thread.thread.id-12.sentence-1)
[13](#thread.thread.id-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1631)
A thread::id object is formatted by
writing its text representation for charT to the output
with additional padding and adjustments as specified by the format specifiers[.](#thread.thread.id-13.sentence-1)
[🔗](#lib:hash,thread::id)
`template<> struct hash<thread::id>;
`
[14](#thread.thread.id-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1643)
The specialization is enabled ([[unord.hash]](unord.hash "22.10.19Class template hash"))[.](#thread.thread.id-14.sentence-1)
#### [32.4.3.3](#thread.thread.constr) Constructors [[thread.thread.constr]](thread.thread.constr)
[🔗](#lib:thread,constructor)
`thread() noexcept;
`
[1](#thread.thread.constr-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1655)
*Effects*: The object does not represent a thread of execution[.](#thread.thread.constr-1.sentence-1)
[2](#thread.thread.constr-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1659)
*Postconditions*: get_id() == id()[.](#thread.thread.constr-2.sentence-1)
[🔗](#lib:thread,constructor_)
`template<class F, class... Args> explicit thread(F&& f, Args&&... args);
`
[3](#thread.thread.constr-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1670)
*Constraints*: remove_cvref_t<F> is not the same type as thread[.](#thread.thread.constr-3.sentence-1)
[4](#thread.thread.constr-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1674)
*Mandates*: The following are all true:
- [(4.1)](#thread.thread.constr-4.1)
is_constructible_v<decay_t<F>, F>,
- [(4.2)](#thread.thread.constr-4.2)
(is_constructible_v<decay_t<Args>, Args> && ...), and
- [(4.3)](#thread.thread.constr-4.3)
is_invocable_v<decay_t<F>, decay_t<Args>...>[.](#thread.thread.constr-4.sentence-1)
[5](#thread.thread.constr-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1683)
*Effects*: The new thread of execution executesinvoke(auto(std::forward<F>(f)), // for invoke, see [[func.invoke]](func.invoke "22.10.5invoke functions")auto(std::forward<Args>(args))...) with the values produced by auto being materialized ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion")) in the constructing thread[.](#thread.thread.constr-5.sentence-1)
Any return value from this invocation is ignored[.](#thread.thread.constr-5.sentence-2)
[*Note [1](#thread.thread.constr-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[.](#thread.thread.constr-5.sentence-3)
— *end note*]
If the invocation of invoke terminates with an uncaught exception,terminate is invoked ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#thread.thread.constr-5.sentence-4)
[6](#thread.thread.constr-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1700)
*Synchronization*: The completion of the invocation of the constructor
synchronizes with the beginning of the invocation of the copy of f[.](#thread.thread.constr-6.sentence-1)
[7](#thread.thread.constr-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1705)
*Postconditions*: get_id() != id()[.](#thread.thread.constr-7.sentence-1)
*this represents the newly started thread[.](#thread.thread.constr-7.sentence-2)
[8](#thread.thread.constr-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1709)
*Throws*: system_error if unable to start the new thread[.](#thread.thread.constr-8.sentence-1)
[9](#thread.thread.constr-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1713)
*Error conditions*:
- [(9.1)](#thread.thread.constr-9.1)
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[.](#thread.thread.constr-9.sentence-1)
[🔗](#lib:thread,constructor__)
`thread(thread&& x) noexcept;
`
[10](#thread.thread.constr-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1728)
*Postconditions*: x.get_id() == id() and get_id() returns the
value of x.get_id() prior to the start of construction[.](#thread.thread.constr-10.sentence-1)
#### [32.4.3.4](#thread.thread.destr) Destructor [[thread.thread.destr]](thread.thread.destr)
[🔗](#lib:thread,destructor)
`~thread();
`
[1](#thread.thread.destr-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1742)
*Effects*: If joinable(), invokes terminate ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#thread.thread.destr-1.sentence-1)
Otherwise, has no effects[.](#thread.thread.destr-1.sentence-2)
[*Note [1](#thread.thread.destr-note-1)*:
Either implicitly detaching or joining a joinable() thread in its
destructor can result in difficult to debug correctness (for detach) or performance
(for join) bugs encountered only when an exception is thrown[.](#thread.thread.destr-1.sentence-3)
These bugs can be avoided by ensuring that
the destructor is never executed while the thread is still joinable[.](#thread.thread.destr-1.sentence-4)
— *end note*]
#### [32.4.3.5](#thread.thread.assign) Assignment [[thread.thread.assign]](thread.thread.assign)
[🔗](#lib:operator=,thread)
`thread& operator=(thread&& x) noexcept;
`
[1](#thread.thread.assign-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1763)
*Effects*: If joinable(), invokes terminate ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#thread.thread.assign-1.sentence-1)
Otherwise, assigns the
state of x to *this and sets x to a default constructed state[.](#thread.thread.assign-1.sentence-2)
[2](#thread.thread.assign-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1769)
*Postconditions*: x.get_id() == id() and get_id() returns the value ofx.get_id() prior to the assignment[.](#thread.thread.assign-2.sentence-1)
[3](#thread.thread.assign-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1774)
*Returns*: *this[.](#thread.thread.assign-3.sentence-1)
#### [32.4.3.6](#thread.thread.member) Members [[thread.thread.member]](thread.thread.member)
[🔗](#lib:swap,thread)
`void swap(thread& x) noexcept;
`
[1](#thread.thread.member-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1787)
*Effects*: Swaps the state of *this and x[.](#thread.thread.member-1.sentence-1)
[🔗](#lib:joinable,thread)
`bool joinable() const noexcept;
`
[2](#thread.thread.member-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1798)
*Returns*: get_id() != id()[.](#thread.thread.member-2.sentence-1)
[🔗](#lib:join,thread)
`void join();
`
[3](#thread.thread.member-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1809)
*Effects*: Blocks until the thread represented by *this has completed[.](#thread.thread.member-3.sentence-1)
[4](#thread.thread.member-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1814)
*Synchronization*: The completion of the thread represented by *this synchronizes with ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))
the corresponding successfuljoin() return[.](#thread.thread.member-4.sentence-1)
[*Note [1](#thread.thread.member-note-1)*:
Operations on*this are not synchronized[.](#thread.thread.member-4.sentence-2)
— *end note*]
[5](#thread.thread.member-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1824)
*Postconditions*: The thread represented by *this has completed[.](#thread.thread.member-5.sentence-1)
get_id() == id()[.](#thread.thread.member-5.sentence-2)
[6](#thread.thread.member-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1828)
*Throws*: system_error when
an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#thread.thread.member-6.sentence-1)
[7](#thread.thread.member-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1833)
*Error conditions*:
- [(7.1)](#thread.thread.member-7.1)
resource_deadlock_would_occur — if deadlock is detected orget_id() == this_thread::get_id()[.](#thread.thread.member-7.1.sentence-1)
- [(7.2)](#thread.thread.member-7.2)
no_such_process — if the thread is not valid[.](#thread.thread.member-7.2.sentence-1)
- [(7.3)](#thread.thread.member-7.3)
invalid_argument — if the thread is not joinable[.](#thread.thread.member-7.3.sentence-1)
[🔗](#lib:detach,thread)
`void detach();
`
[8](#thread.thread.member-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1851)
*Effects*: The thread represented by *this continues execution without the calling thread
blocking[.](#thread.thread.member-8.sentence-1)
When detach() returns, *this no longer represents the possibly continuing
thread of execution[.](#thread.thread.member-8.sentence-2)
When the thread previously represented by *this ends execution, the
implementation releases any owned resources[.](#thread.thread.member-8.sentence-3)
[9](#thread.thread.member-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1858)
*Postconditions*: get_id() == id()[.](#thread.thread.member-9.sentence-1)
[10](#thread.thread.member-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1862)
*Throws*: system_error when
an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#thread.thread.member-10.sentence-1)
[11](#thread.thread.member-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1867)
*Error conditions*:
- [(11.1)](#thread.thread.member-11.1)
no_such_process — if the thread is not valid[.](#thread.thread.member-11.1.sentence-1)
- [(11.2)](#thread.thread.member-11.2)
invalid_argument — if the thread is not joinable[.](#thread.thread.member-11.2.sentence-1)
[🔗](#lib:get_id,thread)
`id get_id() const noexcept;
`
[12](#thread.thread.member-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1881)
*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[.](#thread.thread.member-12.sentence-1)
#### [32.4.3.7](#thread.thread.static) Static members [[thread.thread.static]](thread.thread.static)
[🔗](#lib:hardware_concurrency,thread)
`unsigned hardware_concurrency() noexcept;
`
[1](#thread.thread.static-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1896)
*Returns*: The number of hardware thread contexts[.](#thread.thread.static-1.sentence-1)
[*Note [1](#thread.thread.static-note-1)*:
This value should
only be considered to be a hint[.](#thread.thread.static-1.sentence-2)
— *end note*]
If this value is not computable or
well-defined, an implementation should return 0[.](#thread.thread.static-1.sentence-3)
#### [32.4.3.8](#thread.thread.algorithm) Specialized algorithms [[thread.thread.algorithm]](thread.thread.algorithm)
[🔗](#lib:swap,thread_)
`void swap(thread& x, thread& y) noexcept;
`
[1](#thread.thread.algorithm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1915)
*Effects*: As if by x.swap(y)[.](#thread.thread.algorithm-1.sentence-1)
### [32.4.4](#thread.jthread.class) Class jthread [[thread.jthread.class]](thread.jthread.class)
#### [32.4.4.1](#thread.jthread.class.general) General [[thread.jthread.class.general]](thread.jthread.class.general)
[1](#thread.jthread.class.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1924)
The class jthread provides a mechanism
to create a new thread of execution[.](#thread.jthread.class.general-1.sentence-1)
The functionality is the same as for
class thread ([[thread.thread.class]](#thread.thread.class "32.4.3Class thread"))
with the additional abilities to provide
a stop_token ([[thread.stoptoken]](thread.stoptoken "32.3Stop tokens")) to the new thread of execution,
make stop requests, and automatically join[.](#thread.jthread.class.general-1.sentence-2)
[🔗](#lib:jthread)
namespace std {class jthread {public:// typesusing id = thread::id; using native_handle_type = thread::native_handle_type; // [[thread.jthread.cons]](#thread.jthread.cons "32.4.4.2Constructors, move, and assignment"), 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]](#thread.jthread.mem "32.4.4.3Members"), membersvoid swap(jthread&) noexcept; bool joinable() const noexcept; void join(); void detach();
id get_id() const noexcept;
native_handle_type native_handle(); // see [[thread.req.native]](thread.req.native "32.2.3Native handles")// [[thread.jthread.stop]](#thread.jthread.stop "32.4.4.4Stop token handling"), stop token handling stop_source get_stop_source() noexcept;
stop_token get_stop_token() const noexcept; bool request_stop() noexcept; // [[thread.jthread.special]](#thread.jthread.special "32.4.4.5Specialized algorithms"), specialized algorithmsfriend void swap(jthread& lhs, jthread& rhs) noexcept; // [[thread.jthread.static]](#thread.jthread.static "32.4.4.6Static members"), static membersstatic unsigned int hardware_concurrency() noexcept; private: stop_source ssource; // *exposition only*};}
#### [32.4.4.2](#thread.jthread.cons) Constructors, move, and assignment [[thread.jthread.cons]](thread.jthread.cons)
[🔗](#lib:jthread,constructor)
`jthread() noexcept;
`
[1](#thread.jthread.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1984)
*Effects*: Constructs a jthread object that does not represent
a thread of execution[.](#thread.jthread.cons-1.sentence-1)
[2](#thread.jthread.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L1989)
*Postconditions*: get_id() == id() is true and ssource.stop_possible() is false[.](#thread.jthread.cons-2.sentence-1)
[🔗](#lib:jthread,constructor_)
`template<class F, class... Args> explicit jthread(F&& f, Args&&... args);
`
[3](#thread.jthread.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2001)
*Constraints*: remove_cvref_t<F> is not the same type as jthread[.](#thread.jthread.cons-3.sentence-1)
[4](#thread.jthread.cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2005)
*Mandates*: The following are all true:
- [(4.1)](#thread.jthread.cons-4.1)
is_constructible_v<decay_t<F>, F>,
- [(4.2)](#thread.jthread.cons-4.2)
(is_constructible_v<decay_t<Args>, Args> && ...), and
- [(4.3)](#thread.jthread.cons-4.3)
is_invocable_v<decay_t<F>, decay_t<Args>...> ||
is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>[.](#thread.jthread.cons-4.3.sentence-2)
[5](#thread.jthread.cons-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2014)
*Effects*: Initializes ssource[.](#thread.jthread.cons-5.sentence-1)
The new thread of execution executesinvoke(auto(std::forward<F>(f)), get_stop_token(), // for invoke, see [[func.invoke]](func.invoke "22.10.5invoke functions")auto(std::forward<Args>(args))...) if that expression is well-formed,
otherwiseinvoke(auto(std::forward<F>(f)), auto(std::forward<Args>(args))...) with the values produced by auto being materialized ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion")) in the constructing thread[.](#thread.jthread.cons-5.sentence-2)
Any return value from this invocation is ignored[.](#thread.jthread.cons-5.sentence-3)
[*Note [1](#thread.jthread.cons-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[.](#thread.jthread.cons-5.sentence-4)
— *end note*]
If the invoke expression exits via an exception,terminate is called[.](#thread.jthread.cons-5.sentence-5)
[6](#thread.jthread.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2037)
*Synchronization*: The completion of the invocation of the constructor
synchronizes with the beginning of the invocation of the copy of f[.](#thread.jthread.cons-6.sentence-1)
[7](#thread.jthread.cons-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2042)
*Postconditions*: get_id() != id() is true and ssource.stop_possible() is true and *this represents the newly started thread[.](#thread.jthread.cons-7.sentence-1)
[*Note [2](#thread.jthread.cons-note-2)*:
The calling thread can make a stop request only once,
because it cannot replace this stop token[.](#thread.jthread.cons-7.sentence-2)
— *end note*]
[8](#thread.jthread.cons-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2052)
*Throws*: system_error if unable to start the new thread[.](#thread.jthread.cons-8.sentence-1)
[9](#thread.jthread.cons-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2056)
*Error conditions*:
- [(9.1)](#thread.jthread.cons-9.1)
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[.](#thread.jthread.cons-9.sentence-1)
[🔗](#lib:jthread,constructor__)
`jthread(jthread&& x) noexcept;
`
[10](#thread.jthread.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2072)
*Postconditions*: x.get_id() == id() and get_id() returns the value of x.get_id() prior to the start of construction[.](#thread.jthread.cons-10.sentence-1)
ssource has the value of x.ssource prior to the start of construction
and x.ssource.stop_possible() is false[.](#thread.jthread.cons-10.sentence-2)
[🔗](#lib:jthread,destructor)
`~jthread();
`
[11](#thread.jthread.cons-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2088)
*Effects*: If joinable() is true,
calls request_stop() and then join()[.](#thread.jthread.cons-11.sentence-1)
[*Note [3](#thread.jthread.cons-note-3)*:
Operations on *this are not synchronized[.](#thread.jthread.cons-11.sentence-2)
— *end note*]
[🔗](#lib:operator=,jthread)
`jthread& operator=(jthread&& x) noexcept;
`
[12](#thread.jthread.cons-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2103)
*Effects*: If &x == this is true, there are no effects[.](#thread.jthread.cons-12.sentence-1)
Otherwise, if joinable() is true,
calls request_stop() and then join(),
then assigns the state of x to *this and sets x to a default constructed state[.](#thread.jthread.cons-12.sentence-2)
[13](#thread.jthread.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2111)
*Postconditions*: get_id() returns the value of x.get_id() prior to the assignment[.](#thread.jthread.cons-13.sentence-1)
ssource has the value of x.ssource prior to the assignment[.](#thread.jthread.cons-13.sentence-2)
[14](#thread.jthread.cons-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2118)
*Returns*: *this[.](#thread.jthread.cons-14.sentence-1)
#### [32.4.4.3](#thread.jthread.mem) Members [[thread.jthread.mem]](thread.jthread.mem)
[🔗](#lib:swap,jthread)
`void swap(jthread& x) noexcept;
`
[1](#thread.jthread.mem-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2131)
*Effects*: Exchanges the values of *this and x[.](#thread.jthread.mem-1.sentence-1)
[🔗](#lib:joinable,jthread)
`bool joinable() const noexcept;
`
[2](#thread.jthread.mem-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2142)
*Returns*: get_id() != id()[.](#thread.jthread.mem-2.sentence-1)
[🔗](#lib:join,jthread)
`void join();
`
[3](#thread.jthread.mem-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2153)
*Effects*: Blocks until the thread represented by *this has completed[.](#thread.jthread.mem-3.sentence-1)
[4](#thread.jthread.mem-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2158)
*Synchronization*: The completion of the thread represented by *this synchronizes with ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))
the corresponding successful join() return[.](#thread.jthread.mem-4.sentence-1)
[*Note [1](#thread.jthread.mem-note-1)*:
Operations on *this are not synchronized[.](#thread.jthread.mem-4.sentence-2)
— *end note*]
[5](#thread.jthread.mem-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2167)
*Postconditions*: The thread represented by *this has completed[.](#thread.jthread.mem-5.sentence-1)
get_id() == id()[.](#thread.jthread.mem-5.sentence-2)
[6](#thread.jthread.mem-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2172)
*Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#thread.jthread.mem-6.sentence-1)
[7](#thread.jthread.mem-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2176)
*Error conditions*:
- [(7.1)](#thread.jthread.mem-7.1)
resource_deadlock_would_occur — if deadlock is detected orget_id() == this_thread::get_id()[.](#thread.jthread.mem-7.1.sentence-1)
- [(7.2)](#thread.jthread.mem-7.2)
no_such_process — if the thread is not valid[.](#thread.jthread.mem-7.2.sentence-1)
- [(7.3)](#thread.jthread.mem-7.3)
invalid_argument — if the thread is not joinable[.](#thread.jthread.mem-7.3.sentence-1)
[🔗](#lib:detach,jthread)
`void detach();
`
[8](#thread.jthread.mem-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2194)
*Effects*: The thread represented by *this continues execution
without the calling thread blocking[.](#thread.jthread.mem-8.sentence-1)
When detach() returns,*this no longer represents the possibly continuing thread of execution[.](#thread.jthread.mem-8.sentence-2)
When the thread previously represented by *this ends execution,
the implementation releases any owned resources[.](#thread.jthread.mem-8.sentence-3)
[9](#thread.jthread.mem-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2203)
*Postconditions*: get_id() == id()[.](#thread.jthread.mem-9.sentence-1)
[10](#thread.jthread.mem-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2207)
*Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#thread.jthread.mem-10.sentence-1)
[11](#thread.jthread.mem-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2211)
*Error conditions*:
- [(11.1)](#thread.jthread.mem-11.1)
no_such_process — if the thread is not valid[.](#thread.jthread.mem-11.1.sentence-1)
- [(11.2)](#thread.jthread.mem-11.2)
invalid_argument — if the thread is not joinable[.](#thread.jthread.mem-11.2.sentence-1)
[🔗](#lib:get_id,jthread)
`id get_id() const noexcept;
`
[12](#thread.jthread.mem-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2225)
*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[.](#thread.jthread.mem-12.sentence-1)
#### [32.4.4.4](#thread.jthread.stop) Stop token handling [[thread.jthread.stop]](thread.jthread.stop)
[🔗](#lib:get_stop_source,jthread)
`stop_source get_stop_source() noexcept;
`
[1](#thread.jthread.stop-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2241)
*Effects*: Equivalent to: return ssource;
[🔗](#lib:get_stop_token,jthread)
`stop_token get_stop_token() const noexcept;
`
[2](#thread.jthread.stop-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2252)
*Effects*: Equivalent to: return ssource.get_token();
[🔗](#lib:request_stop,jthread)
`bool request_stop() noexcept;
`
[3](#thread.jthread.stop-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2263)
*Effects*: Equivalent to: return ssource.request_stop();
#### [32.4.4.5](#thread.jthread.special) Specialized algorithms [[thread.jthread.special]](thread.jthread.special)
[🔗](#lib:swap,jthread_)
`friend void swap(jthread& x, jthread& y) noexcept;
`
[1](#thread.jthread.special-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2277)
*Effects*: Equivalent to: x.swap(y)[.](#thread.jthread.special-1.sentence-1)
#### [32.4.4.6](#thread.jthread.static) Static members [[thread.jthread.static]](thread.jthread.static)
[🔗](#lib:hardware_concurrency,jthread)
`static unsigned int hardware_concurrency() noexcept;
`
[1](#thread.jthread.static-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2290)
*Returns*: thread::hardware_concurrency()[.](#thread.jthread.static-1.sentence-1)
### [32.4.5](#thread.thread.this) Namespace this_thread [[thread.thread.this]](thread.thread.this)
namespace std::this_thread { thread::id get_id() noexcept; void yield() noexcept; template<class Clock, class Duration>void sleep_until(const chrono::time_point<Clock, Duration>& abs_time); template<class Rep, class Period>void sleep_for(const chrono::duration<Rep, Period>& rel_time);}
[🔗](#lib:get_id,this_thread)
`thread::id this_thread::get_id() noexcept;
`
[1](#thread.thread.this-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2316)
*Returns*: An object of type thread::id that uniquely identifies the current thread of execution[.](#thread.thread.this-1.sentence-1)
Every invocation from this thread of execution returns the same value[.](#thread.thread.this-1.sentence-2)
The object returned does not compare equal to
a default-constructed thread::id[.](#thread.thread.this-1.sentence-3)
[🔗](#lib:yield,this_thread)
`void this_thread::yield() noexcept;
`
[2](#thread.thread.this-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2331)
*Effects*: Offers the implementation the opportunity to reschedule[.](#thread.thread.this-2.sentence-1)
[3](#thread.thread.this-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2335)
*Synchronization*: None[.](#thread.thread.this-3.sentence-1)
[🔗](#lib:sleep_until,this_thread)
`template<class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
`
[4](#thread.thread.this-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2347)
*Effects*: Blocks the calling thread for the absolute timeout ([[thread.req.timing]](thread.req.timing "32.2.4Timing specifications")) specified
by abs_time[.](#thread.thread.this-4.sentence-1)
[5](#thread.thread.this-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2353)
*Synchronization*: None[.](#thread.thread.this-5.sentence-1)
[6](#thread.thread.this-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2357)
*Throws*: Timeout-related exceptions ([[thread.req.timing]](thread.req.timing "32.2.4Timing specifications"))[.](#thread.thread.this-6.sentence-1)
[🔗](#lib:sleep_for,this_thread)
`template<class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
`
[7](#thread.thread.this-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2369)
*Effects*: Blocks the calling thread for the relative timeout ([[thread.req.timing]](thread.req.timing "32.2.4Timing specifications")) specified
by rel_time[.](#thread.thread.this-7.sentence-1)
[8](#thread.thread.this-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2375)
*Synchronization*: None[.](#thread.thread.this-8.sentence-1)
[9](#thread.thread.this-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2379)
*Throws*: Timeout-related exceptions ([[thread.req.timing]](thread.req.timing "32.2.4Timing specifications"))[.](#thread.thread.this-9.sentence-1)