1050 lines
40 KiB
Markdown
1050 lines
40 KiB
Markdown
[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.1 Header <compare> synopsis")namespace std {// [[thread.thread.class]](#thread.thread.class "32.4.3 Class thread"), class threadclass thread; void swap(thread& x, thread& y) noexcept; // [[thread.jthread.class]](#thread.jthread.class "32.4.4 Class jthread"), class jthreadclass jthread; // [[thread.thread.this]](#thread.thread.this "32.4.5 Namespace 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.2 Class thread::id"), class thread::idclass id; using native_handle_type = *implementation-defined*; // see [[thread.req.native]](thread.req.native "32.2.3 Native 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.6 Members"), 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.3 Native 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.3 Class 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.2 Class 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.2 Properties 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.8 Sorting 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.2 Standard 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.19 Class 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.5 invoke functions")auto(std::forward<Args>(args))...) with the values produced by auto being materialized ([[conv.rval]](conv.rval "7.3.5 Temporary 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.2 The 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.2 The 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.2 The 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.2 Multi-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.2 Exceptions"))[.](#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.2 Exceptions"))[.](#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.3 Class thread"))
|
||
with the additional abilities to provide
|
||
a stop_token ([[thread.stoptoken]](thread.stoptoken "32.3 Stop 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.2 Constructors, 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.3 Members"), 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.3 Native handles")// [[thread.jthread.stop]](#thread.jthread.stop "32.4.4.4 Stop 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.5 Specialized algorithms"), specialized algorithmsfriend void swap(jthread& lhs, jthread& rhs) noexcept; // [[thread.jthread.static]](#thread.jthread.static "32.4.4.6 Static 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.5 invoke 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.5 Temporary 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.2 Multi-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.2 Exceptions"))[.](#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.2 Exceptions"))[.](#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.4 Timing 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.4 Timing 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.4 Timing 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.4 Timing specifications"))[.](#thread.thread.this-9.sentence-1)
|