-
Notifications
You must be signed in to change notification settings - Fork 813
[2026-06 LWG Motion 18] P2019R9 Thread attributes #9121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -1474,6 +1474,13 @@ | |||||||
| public: | ||||||||
| // \ref{thread.thread.id}, class \tcode{thread::id} | ||||||||
| class id; | ||||||||
|
|
||||||||
| // \ref{thread.attributes}, thread attributes | ||||||||
| template<@\libconcept{same_as}@<char> T> class name_hint; | ||||||||
| template<class T> name_hint(const T*) -> name_hint<T>; | ||||||||
| template<class T> name_hint(basic_string<T>) -> name_hint<T>; | ||||||||
| class stack_size_hint; | ||||||||
|
|
||||||||
| using native_handle_type = @\impdefnc@; // see~\ref{thread.req.native} | ||||||||
|
|
||||||||
| // construct/copy/destroy | ||||||||
|
|
@@ -1499,6 +1506,98 @@ | |||||||
| } | ||||||||
| \end{codeblock} | ||||||||
|
|
||||||||
| \rSec3[thread.attributes]{Thread attributes} | ||||||||
|
|
||||||||
| \pnum | ||||||||
| \defnx{thread attribute}{Thread attributes} | ||||||||
| can be used to define additional implementation-defined behaviors | ||||||||
| on a \tcode{thread} or \tcode{jthread} object. | ||||||||
|
|
||||||||
| \pnum | ||||||||
| The set of \defnadj{thread attribute}{types} contains | ||||||||
| \tcode{thread::name_hint}, | ||||||||
| \tcode{thread::stack_size_hint}, and | ||||||||
| an \impldef{set of additional thread-attributes} set of additional thread-attributes. | ||||||||
|
|
||||||||
| \pnum | ||||||||
| When an object of a thread attribute type is passed to | ||||||||
| a \tcode{thread} or \tcode{jthread} constructor, | ||||||||
| it may affect the new thread's behavior. | ||||||||
|
|
||||||||
| \indexlibraryglobal{thread::name_hint}% | ||||||||
| \begin{codeblock} | ||||||||
| template<@\libconcept{same_as}@<char> T> | ||||||||
| class thread::name_hint { | ||||||||
| public: | ||||||||
| constexpr explicit name_hint(basic_string_view<T> n) noexcept; | ||||||||
| name_hint(name_hint&&) = delete; | ||||||||
| name_hint(const name_hint&) = delete; | ||||||||
| private: | ||||||||
| basic_string_view<T> @\exposid{name}@; // \expos | ||||||||
| }; | ||||||||
| \end{codeblock} | ||||||||
|
|
||||||||
| \pnum | ||||||||
| The \tcode{name_hint} thread attribute can be used to set the name of a thread | ||||||||
| for debugging purposes or platform-specific display mechanisms. | ||||||||
|
|
||||||||
| \recommended | ||||||||
| Implementations should not store the value of the \tcode{name_hint} attribute | ||||||||
| in the \tcode{thread} or \tcode{jthread} object. | ||||||||
|
|
||||||||
| \recommended | ||||||||
| %FIXME: ordinary literal encoding? Literal encoding of T? What is "THE literal encoding"? | ||||||||
| \exposid{name} is interpreted as a string in the literal encoding. | ||||||||
|
Comment on lines
+1549
to
+1550
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At this moment, I believe the literal encoding must be the ordinary literal encoding because
Suggested change
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At this point it cannot be anything else, yeah. I'm wondering in which direction we want to resolve this though, and that depends on how likely support for more character types is in the future. If we say "ordinary literal encoding" now, we will need to change that wording if more support is added. |
||||||||
|
|
||||||||
| \indexlibraryctor{thread::name_hint}% | ||||||||
| \begin{itemdecl} | ||||||||
| constexpr explicit name_hint(basic_string_view<T> n) noexcept; | ||||||||
| \end{itemdecl} | ||||||||
|
|
||||||||
| \begin{itemdescr} | ||||||||
| \pnum | ||||||||
| \effects | ||||||||
| Initializes \exposid{name} with \tcode{n}. | ||||||||
| \end{itemdescr} | ||||||||
|
|
||||||||
| \indexlibraryglobal{thread::stack_size_hint}% | ||||||||
| \begin{codeblock} | ||||||||
| namespace std { | ||||||||
| class thread::stack_size_hint { | ||||||||
| public: | ||||||||
| constexpr explicit stack_size_hint(size_t s) noexcept; | ||||||||
| private: | ||||||||
| size_t @\exposid{size}@; // \expos | ||||||||
| }; | ||||||||
| } | ||||||||
| \end{codeblock} | ||||||||
|
|
||||||||
| \pnum | ||||||||
| \tcode{stack_size_hint} can be used to configure a desired size in bytes | ||||||||
| for platform-specific storage required for a thread. | ||||||||
| \begin{note} | ||||||||
| Such storage is typically used for variables with automatic storage duration. | ||||||||
| \end{note} | ||||||||
|
|
||||||||
| \pnum | ||||||||
| The stack size set by the implementation may be adjusted up or down | ||||||||
| to meet platform-specific requirements. | ||||||||
|
|
||||||||
| \pnum | ||||||||
| If \exposid{size} is zero, | ||||||||
| the thread attribute is ignored. | ||||||||
|
|
||||||||
| \indexlibraryctor{thread::stack_size_hint}% | ||||||||
| \begin{itemdecl} | ||||||||
| constexpr explicit stack_size_hint(size_t s) noexcept; | ||||||||
| \end{itemdecl} | ||||||||
|
|
||||||||
| \begin{itemdescr} | ||||||||
| \pnum | ||||||||
| \effects | ||||||||
| Initializes \exposid{size} with \tcode{s}. | ||||||||
| \end{itemdescr} | ||||||||
|
|
||||||||
| \rSec3[thread.thread.id]{Class \tcode{thread::id}} | ||||||||
|
|
||||||||
| \indexlibraryglobal{thread::id}% | ||||||||
|
|
@@ -1675,29 +1774,64 @@ | |||||||
|
|
||||||||
| \indexlibraryctor{thread}% | ||||||||
| \begin{itemdecl} | ||||||||
| template<class F, class... Args> explicit thread(F&& f, Args&&... args); | ||||||||
| template<class... Args> explicit thread(Args&&... args); | ||||||||
| \end{itemdecl} | ||||||||
|
|
||||||||
| \begin{itemdescr} | ||||||||
| \pnum | ||||||||
| \constraints | ||||||||
| \tcode{remove_cvref_t<F>} is not the same type as \tcode{thread}. | ||||||||
| \begin{itemize} | ||||||||
| \item | ||||||||
| \tcode{Args} is not an empty pack, and | ||||||||
| \item | ||||||||
| \tcode{remove_cvref_t<F Args...[0]>} is not the same type as \tcode{thread}. | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| \end{itemize} | ||||||||
|
|
||||||||
| \pnum | ||||||||
| \begin{itemize} | ||||||||
| \item | ||||||||
| Let $i$ be the smallest value such that | ||||||||
| \tcode{decay_t<Args...[$i$]>} | ||||||||
| is not a thread attribute type. | ||||||||
| If no such $i$ exists, the program is ill-formed. | ||||||||
| \item | ||||||||
| Let \tcode{F} be \tcode{Args...[$i$]}. | ||||||||
| \item | ||||||||
| Let \tcode{f} be \tcode{args...[$i$]}. | ||||||||
| \item | ||||||||
| Let \tcode{Attrs} be a pack of the types | ||||||||
| \tcode{Args...[$j$]} for each $j$ | ||||||||
| such that $0 \leq j < i$. | ||||||||
| \item | ||||||||
| Let \tcode{attrs} be a pack of the expressions | ||||||||
| \tcode{args...[$j$]} for each $j$ | ||||||||
| such that $0 \leq j < i$. | ||||||||
| \item | ||||||||
| Let \tcode{FArgs} be a pack of the types | ||||||||
| \tcode{Args...[$j$]} for each $j$ | ||||||||
| such that $i < j < \tcode{sizeof...(args)}$. | ||||||||
| \item | ||||||||
| Let \tcode{fargs} be a pack of the expressions | ||||||||
| \tcode{args...[$j$]} for each $j$ | ||||||||
| such that $i < j < \tcode{sizeof...(args)}$. | ||||||||
| \end{itemize} | ||||||||
|
|
||||||||
| \pnum | ||||||||
| \mandates | ||||||||
| The following are all \tcode{true}: | ||||||||
| \begin{itemize} | ||||||||
| \item \tcode{is_constructible_v<decay_t<F>, F>}, | ||||||||
| \item \tcode{(is_constructible_v<decay_t<Args>, Args> \&\& ...)}, and | ||||||||
| \item \tcode{is_invocable_v<decay_t<F>, decay_t<Args>...>}. | ||||||||
| \item \tcode{(is_constructible_v<decay_t<FArgs>, FArgs> \&\& ...)}, | ||||||||
| \item \tcode{is_invocable_v<decay_t<F>, decay_t<FArgs>...>}, and | ||||||||
| \item No type is present more than once in the pack \tcode{remove_cvref_t<Attrs>}. | ||||||||
| \end{itemize} | ||||||||
|
|
||||||||
| \pnum | ||||||||
| \effects | ||||||||
| The new thread of execution executes | ||||||||
| \begin{codeblock} | ||||||||
| invoke(auto(std::forward<F>(f)), // for \tcode{invoke}, see \ref{func.invoke} | ||||||||
| auto(std::forward<Args>(args))...) | ||||||||
| auto(std::forward<FArgs>(fargs))...) | ||||||||
| \end{codeblock} | ||||||||
| with the values produced by \tcode{auto} | ||||||||
| being materialized\iref{conv.rval} in the constructing thread. | ||||||||
|
|
@@ -1708,6 +1842,8 @@ | |||||||
| \end{note} | ||||||||
| If the invocation of \tcode{invoke} terminates with an uncaught exception, | ||||||||
| \tcode{terminate} is invoked\iref{except.terminate}. | ||||||||
| The parameters \tcode{attrs...} | ||||||||
| can affect the behavior of the new thread\iref{thread.attributes}. | ||||||||
|
|
||||||||
| \pnum | ||||||||
| \sync | ||||||||
|
|
@@ -1951,9 +2087,12 @@ | |||||||
| using id = thread::id; | ||||||||
| using native_handle_type = thread::native_handle_type; | ||||||||
|
|
||||||||
| template<class T> using name_hint = thread::name_hint<T>; | ||||||||
| using stack_size_hint = thread::stack_size_hint; | ||||||||
|
|
||||||||
| // \ref{thread.jthread.cons}, constructors, move, and assignment | ||||||||
| jthread() noexcept; | ||||||||
| template<class F, class... Args> explicit jthread(F&& f, Args&&... args); | ||||||||
| template<class... Args> explicit jthread(Args&&... args); | ||||||||
| ~jthread(); | ||||||||
| jthread(const jthread&) = delete; | ||||||||
| jthread(jthread&&) noexcept; | ||||||||
|
|
@@ -2006,21 +2145,52 @@ | |||||||
|
|
||||||||
| \indexlibraryctor{jthread}% | ||||||||
| \begin{itemdecl} | ||||||||
| template<class F, class... Args> explicit jthread(F&& f, Args&&... args); | ||||||||
| template<class... Args> explicit jthread(Args&&... args); | ||||||||
| \end{itemdecl} | ||||||||
|
|
||||||||
| \begin{itemdescr} | ||||||||
| \pnum | ||||||||
| \constraints | ||||||||
| \tcode{remove_cvref_t<F>} is not the same type as \tcode{jthread}. | ||||||||
| \tcode{Args} is not an empty pack, and | ||||||||
| \tcode{remove_cvref_t<F Args...[0]>} is not the same type as \tcode{jthread}. | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
|
||||||||
| \pnum | ||||||||
| \begin{itemize} | ||||||||
| \item | ||||||||
| Let $i$ be the smallest value such that | ||||||||
| \tcode{decay_t<Args...[$i$]>} | ||||||||
| is not a thread attribute type. | ||||||||
| If no such $i$ exists, the program is ill-formed. | ||||||||
| \item | ||||||||
| Let \tcode{F} be \tcode{Args...[$i$]}. | ||||||||
| \item | ||||||||
| Let \tcode{f} be \tcode{args...[$i$]}. | ||||||||
| \item | ||||||||
| Let \tcode{Attrs} be a pack of the types | ||||||||
| \tcode{Args...[$j$]} for each $j$ | ||||||||
| such that $0 \leq j < i$. | ||||||||
| \item | ||||||||
| Let \tcode{attrs} be a pack of the expressions | ||||||||
| \tcode{args...[$j$]} for each $j$ | ||||||||
| such that $0 \leq j < i$. | ||||||||
| \item | ||||||||
| Let \tcode{FArgs} be a pack of the types | ||||||||
| \tcode{Args...[$j$]} for each $j$ | ||||||||
| such that $i < j < \tcode{sizeof...(args)}$. | ||||||||
| \item | ||||||||
| Let \tcode{fargs} be a pack of the expressions | ||||||||
| \tcode{args...[$j$]} for each $j$ | ||||||||
| such that $i < j < \tcode{sizeof...(args)}$. | ||||||||
| \end{itemize} | ||||||||
|
|
||||||||
| \pnum | ||||||||
| \mandates | ||||||||
| The following are all \tcode{true}: | ||||||||
| \begin{itemize} | ||||||||
| \item \tcode{is_constructible_v<decay_t<F>, F>}, | ||||||||
| \item \tcode{(is_constructible_v<decay_t<Args>, Args> \&\& ...)}, and | ||||||||
| \item \tcode{is_invocable_v<decay_t<F>, decay_t<Args>...> ||} \\ \tcode{is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>}. | ||||||||
| \item \tcode{(is_constructible_v<decay_t<FArgs>, FArgs> \&\& ...)}, | ||||||||
| \item \tcode{is_invocable_v<decay_t<F>, decay_t<FArgs>...> ||} \\ \tcode{is_invocable_v<decay_t<F>, stop_token, decay_t<FArgs>...>}, and | ||||||||
| \item No type is present more than once in the pack \tcode{remove_cvref_t<Attrs>}. | ||||||||
| \end{itemize} | ||||||||
|
|
||||||||
| \pnum | ||||||||
|
|
@@ -2029,12 +2199,12 @@ | |||||||
| The new thread of execution executes | ||||||||
| \begin{codeblock} | ||||||||
| invoke(auto(std::forward<F>(f)), get_stop_token(), // for \tcode{invoke}, see \ref{func.invoke} | ||||||||
| auto(std::forward<Args>(args))...) | ||||||||
| auto(std::forward<FArgs>(fargs))...) | ||||||||
| \end{codeblock} | ||||||||
| if that expression is well-formed, | ||||||||
| otherwise | ||||||||
| \begin{codeblock} | ||||||||
| invoke(auto(std::forward<F>(f)), auto(std::forward<Args>(args))...) | ||||||||
| invoke(auto(std::forward<F>(f)), auto(std::forward<FArgs>(fargs))...) | ||||||||
| \end{codeblock} | ||||||||
| with the values produced by \tcode{auto} | ||||||||
| being materialized\iref{conv.rval} in the constructing thread. | ||||||||
|
|
@@ -2045,6 +2215,11 @@ | |||||||
| \end{note} | ||||||||
| If the \tcode{invoke} expression exits via an exception, | ||||||||
| \tcode{terminate} is called. | ||||||||
| The parameters \tcode{attrs...} | ||||||||
| %FIXME: why do we have iref{thread.attributes} for thread for the same wording, | ||||||||
| %but not for jthread? | ||||||||
| %While we're at it, could this not be a note? | ||||||||
| can affect the behavior of the new thread. | ||||||||
|
|
||||||||
| \pnum | ||||||||
| \sync | ||||||||
|
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should rename this to
name_, possibly in a follow-up commit or PR. Same for (size->)size_.