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

401 lines
15 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.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.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[.](#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)