[thread.jthread.class] # 32 Concurrency support library [[thread]](./#thread) ## 32.4 Threads [[thread.threads]](thread.threads#thread.jthread.class) ### 32.4.4 Class jthread [thread.jthread.class] #### [32.4.4.1](#general) General [[thread.jthread.class.general]](thread.jthread.class.general) [1](#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[.](#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[.](#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 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 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 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, F>, - [(4.2)](#thread.jthread.cons-4.2) (is_constructible_v, Args> && ...), and - [(4.3)](#thread.jthread.cons-4.3) is_invocable_v, decay_t...> || is_invocable_v, stop_token, decay_t...>[.](#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)), get_stop_token(), // for invoke, see [[func.invoke]](func.invoke "22.10.5 invoke functions")auto(std::forward(args))...) if that expression is well-formed, otherwiseinvoke(auto(std::forward(f)), auto(std::forward(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)