[thread.thread.class]

# 32 Concurrency support library [[thread]](./#thread)

## 32.4 Threads [[thread.threads]](thread.threads#thread.thread.class)

### 32.4.3 Class thread [thread.thread.class]

#### [32.4.3.1](#general) General [[thread.thread.class.general]](thread.thread.class.general)

[1](#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[.](#general-1.sentence-1)

A thread object uniquely represents a particular thread of
execution[.](#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[.](#general-1.sentence-3)

A
thread of execution is [*detached*](#def:detached) when no thread object represents that thread[.](#general-1.sentence-4)

Objects of class thread can be in a state that does not represent a thread of
execution[.](#general-1.sentence-5)

[*Note [1](#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[.](#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.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)
