From 4c0c1fddc079d4d2b89ebbec587b307f88b2ac70 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Sat, 25 Nov 2023 14:21:26 +0100 Subject: [PATCH] Updates in Kona --- src/D2019.tex | 273 +++++++++++++++++++++++++++++--------------------- src/D2989.tex | 64 ++++++------ src/wg21.cls | 20 ++-- 3 files changed, 202 insertions(+), 155 deletions(-) diff --git a/src/D2019.tex b/src/D2019.tex index ad98a93..8a7ba4d 100644 --- a/src/D2019.tex +++ b/src/D2019.tex @@ -82,7 +82,7 @@ \section{Example} \begin{colorblock} void f(int); int main() { - std::jthread thread(std::thread_name("Worker"), std::thread_stack_size(512*1024), f, 42); + std::jthread thread(std::thread_name_hint("Worker"), std::thread_stack_size_hint(512*1024), f, 42); return 0; } \end{colorblock} @@ -414,13 +414,13 @@ \subsection{I cannot implement that on my platform?} \begin{colorblock} namespace std { -struct thread_name { - constexpr thread_name(std::string_view str) noexcept {}; - constexpr thread_name(std::u8string_view str) noexcept {}; +struct thread_name_hint { + constexpr explicit thread_name_hint(std::string_view str) noexcept {}; + constexpr explicit thread_name_hint(std::u8string_view str) noexcept {}; }; -struct thread_stack_size { - constexpr thread_stack_size(std::size_t) noexcept {} +struct thread_stack_sizeĀ£_hint { + constexpr explicit thread_stack_size_hint(std::size_t) noexcept {} }; \end{colorblock} @@ -494,7 +494,7 @@ \subsection{Design} This is made slightly easier by pack indexing (\paper{P2662R2}) \href{https://compiler-explorer.com/z/n8vYb7Tar}{[Compiler Explorer]}. -\tcode{thread_name} makes a copy of this argument and supports non-null terminated strings, and \tcode{u8} strings, as to +\tcode{thread_name_hint} makes a copy of this argument and supports non-null terminated strings, and \tcode{u8} strings, as to portably support environments with utf-8 execution encodings (Linux), environments where Unicode encodings can be preserved (Windows), and other environments. @@ -545,6 +545,49 @@ \subsubsection{Can we add setters/getters later?} This could be added later (and isn't ABI breaking). + +\subsection{\tcode{constexpr} Constructors} + +During R4 it was suggested to remove the constexpr on the constructor of thread attributes. +The idea was that an implementation could eagerly set the attribute on a pthread_attr_t. +However, pthread_attr_t is a collection of attributes rather than a single attribute so this +implementation strategy is not viable. Besides, on platforms were \tcode{pthread_attr_t} is +available the thread name size can't be more than a few bytes. +And on platforms where large thread names are theoretically possible (ie windows), a copy is +unavoidable. As such, removing \tcode{constexpr} would pessimize the windows case, and not +improve the posix case. + +\subsection{Copyable attributes} + +LEWG suggested making attributes non-copyable. While we do not know of a technical limitation +with that, we also do not see a motivation for doing so, nor can we imagine a case where using thread attributes +would lead to performance degradation. + +\subsection{Copy in \tcode{thread_name_hint}} + +\tcode{thread_name_hint} copies the constructor argument to avoid lifetime issues. +Making the constructors move-only or non-movable would not avoid the lifetime issues. + + +\subsection{\tcode{thread::name_hint} vs \tcode{thread_name_hint}} + +LEWG had a mild suggestion of using \tcode{thread::name_hint} instead of \tcode{std::thread_name_hint}. +I do not have a strong opinion. + +\begin{colorblock} +class thread { + class id; + class name_hint; + class stack_size_hint; +}; + +class jthread { + using id = thread::id; + using name_hint = thread::name_hint; + using stack_size_hint = thread::stack_size_hint; +}; +\end{colorblock} + \section{Implementation} A \href{https://github.com/cor3ntin/llvm-project/tree/corentin/thread_name_p2019}{prototype implementation} for libc++ (supporting only POSIX) threads has been created to validate the design. @@ -617,99 +660,154 @@ \section{Wording} \rSec1[thread.threads]{Threads} -\rSec2[thread.threads.general]{General} +%\rSec2[thread.threads.general]{General} +% +%\pnum +%\ref{thread.threads} describes components that can be used to create and manage threads. +%\begin{note} +% These threads are intended to map one-to-one with operating system threads. +%\end{note} +% +%\rSec2[thread.syn]{Header \tcode{} synopsis} +% +%\begin{codeblock} +%#include // see \ref{compare.syn} +% +%namespace std { +%\end{codeblock} +%\begin{addedblock} +%\begin{codeblock} +% % class thread_name_hint; +% % class thread_stack_size_hint; +%\end{codeblock} +%\end{addedblock} +%\begin{codeblock} +% // \ref{thread.thread.class}, class \tcode{thread} +% class thread; +% +% void swap(thread& x, thread& y) noexcept; +% +% // \ref{thread.jthread.class}, class \tcode{jthread} +% class jthread; +% +% // \ref{thread.thread.this}, namespace \tcode{this_thread} +% namespace this_thread { +% thread::id get_id() noexcept; +% +% void yield() noexcept; +% template +% void sleep_until(const chrono::time_point& abs_time); +% template +% void sleep_for(const chrono::duration& rel_time); +% } +%} +%\end{codeblock} +\begin{addedblock} +\rSec2[thread.thread.class]{Class \tcode{thread}} + +\rSec3[thread.thread.class.general]{General} \pnum -\ref{thread.threads} describes components that can be used to create and manage threads. +The class \tcode{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. A \tcode{thread} object uniquely represents a particular thread of +execution. That representation may be transferred to other \tcode{thread} objects in such a way +that no two \tcode{thread} objects simultaneously represent the same thread of execution. A +thread of execution is \term{detached} when no \tcode{thread} object represents that thread. +Objects of class \tcode{thread} can be in a state that does not represent a thread of +execution. \begin{note} - These threads are intended to map one-to-one with operating system threads. + A \tcode{thread} object does not represent a thread of execution after + default construction, after being moved from, or after a successful call to \tcode{detach} or + \tcode{join}. \end{note} -\rSec2[thread.syn]{Header \tcode{} synopsis} - \begin{codeblock} -#include // see \ref{compare.syn} - namespace std { -\end{codeblock} -\begin{addedblock} -\begin{codeblock} - class thread_name; - class thread_stack_size; -\end{codeblock} -\end{addedblock} -\begin{codeblock} - // \ref{thread.thread.class}, class \tcode{thread} - class thread; +class thread { + public: + class thread::id; + class id; + using native_handle_type = @\impdefnc@; // see~\ref{thread.req.native} - void swap(thread& x, thread& y) noexcept; + // construct/copy/destroy + thread() noexcept; + template<@\removed{class F,}@ class... Args> explicit thread(@\removed{F\&\& f,}@ Args&&... args); - // \ref{thread.jthread.class}, class \tcode{jthread} - class jthread; + ~thread(); + thread(const thread&) = delete; + thread(thread&&) noexcept; + thread& operator=(const thread&) = delete; + thread& operator=(thread&&) noexcept; - // \ref{thread.thread.this}, namespace \tcode{this_thread} - namespace this_thread { - thread::id get_id() noexcept; + // \ref{thread.thread.member}, members + void swap(thread&) noexcept; + bool joinable() const noexcept; + void join(); + void detach(); + id get_id() const noexcept; + native_handle_type native_handle(); // see~\ref{thread.req.native} - void yield() noexcept; - template - void sleep_until(const chrono::time_point& abs_time); - template - void sleep_for(const chrono::duration& rel_time); - } + // static members + static unsigned int hardware_concurrency() noexcept; +}; } \end{codeblock} -\begin{addedblock} -\rSec2[thread.attributes]{Thread Attributes} + +\rSec3[thread.attributes]{Thread Attributes} Thread attributes can be used to define additional implementation-defined behaviors on a \tcode{thread} or \tcode{jthread} object. %\recommended %Implementations may provide additional platform-specific thread attributes derived from \tcode{thread_attribute} using reserved names. -\rSec3[thread.thread.name.class]{Class \tcode{thread_name}} +\rSec4[thread.thread.name.hint]{Class \tcode{thread::name_hint}} \begin{codeblock} -class thread_name { -public: - constexpr thread_name(std::string_view name) noexcept; - constexpr thread_name(std::u8string_view name) noexcept; -private: - @\impdefnc@ __name[@\impdefnc@]; // \expos +namespace std { +class name_hint { + public: + constexpr explicit name_hint(std::string_view name) noexcept; + constexpr explicit name_hint(std::u8string_view name) noexcept; + private: + @\impdefnc@ __name[@\impdefnc@]; // \expos }; +} \end{codeblock} \recommended -The \tcode{thread_name} thread attribute, can be used +The \tcode{name_hint} thread attribute, can be used to set the name of a thread such that the name could be used for debugging or platform-specific display mechanisms. The name should not be stored in the \tcode{std::thread} or \tcode{std::jthread} object. \begin{itemdecl} -constexpr thread_name(std::string_view name) noexcept; -constexpr thread_name(std::u8string_view name) noexcept; + constexpr name_hint(std::string_view name) noexcept; + constexpr name_hint(std::u8string_view name) noexcept; \end{itemdecl} \begin{itemdescr} -\effects Initializes \tcode{__name} with \tcode{name} in an implementation-defined manner. + \effects Initializes \tcode{__name} with \tcode{name} in an implementation-defined manner. -\recommended If \tcode{__name} is not large enough to store the value of \tcode{name}, - the thread name might be truncated. If the implementation performs a text conversion - during the initialization of \tcode{__name} and if \tcode{name} is a valid code unit sequence - in the encoding associated with its type, \tcode{__name} should be a valid code unit sequence in its - associated encoding. + \recommended If \tcode{__name} is not large enough to store the value of \tcode{name}, + the thread name might be truncated. If the implementation performs a text conversion + during the initialization of \tcode{__name} and if \tcode{name} is a valid code unit sequence + in the encoding associated with its type, \tcode{__name} should be a valid code unit sequence in its + associated encoding. \end{itemdescr} -\rSec3[thread.thread.stack.size.class]{Class \tcode{thread_stack_size}} +\rSec4[thread.thread.stack.hint]{Class \tcode{thread::stack_size_hint}} \begin{codeblock} -class thread_stack_size { -public: - constexpr thread_stack_size(std::size_t size) noexcept; -private: - constexpr std::size_t __size; // \expos +namespace std { +class thread::stack_size_hint { + public: + constexpr stack_size_hint(std::size_t size) noexcept; + private: + constexpr std::size_t __size; // \expos }; +} \end{codeblock} \recommended @@ -720,66 +818,15 @@ \section{Wording} \begin{itemdecl} -constexpr thread_stack_size(std::size_t size) noexcept; + constexpr stack_size_hint(std::size_t size) noexcept; \end{itemdecl} \begin{itemdescr} -\effects Initializes \tcode{__size} with \tcode{size} in an implementation-defined manner. + \effects Initializes \tcode{__size} with \tcode{size} in an implementation-defined manner. \end{itemdescr} \end{addedblock} -\rSec2[thread.thread.class]{Class \tcode{thread}} - -\rSec3[thread.thread.class.general]{General} - -\pnum -The class \tcode{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. A \tcode{thread} object uniquely represents a particular thread of -execution. That representation may be transferred to other \tcode{thread} objects in such a way -that no two \tcode{thread} objects simultaneously represent the same thread of execution. A -thread of execution is \term{detached} when no \tcode{thread} object represents that thread. -Objects of class \tcode{thread} can be in a state that does not represent a thread of -execution. -\begin{note} - A \tcode{thread} object does not represent a thread of execution after - default construction, after being moved from, or after a successful call to \tcode{detach} or - \tcode{join}. -\end{note} - -\begin{codeblock} -namespace std { -class thread { - public: - class thread::id; - class id; - using native_handle_type = @\impdefnc@; // see~\ref{thread.req.native} - - // construct/copy/destroy - thread() noexcept; - template<@\removed{class F,}@ class... Args> explicit thread(@\removed{F\&\& f,}@ Args&&... args); - - ~thread(); - thread(const thread&) = delete; - thread(thread&&) noexcept; - thread& operator=(const thread&) = delete; - thread& operator=(thread&&) noexcept; - - // \ref{thread.thread.member}, members - void swap(thread&) noexcept; - bool joinable() const noexcept; - void join(); - void detach(); - id get_id() const noexcept; - native_handle_type native_handle(); // see~\ref{thread.req.native} - - // static members - static unsigned int hardware_concurrency() noexcept; -}; -} -\end{codeblock} - \rSec3[thread.thread.constr]{Constructors} diff --git a/src/D2989.tex b/src/D2989.tex index 70f238d..33b709a 100644 --- a/src/D2989.tex +++ b/src/D2989.tex @@ -507,7 +507,7 @@ \subsection{Syntax} \item \tcode{__any} or \tcode{__universal} would also work, but C++ doesn't traditionally embrace underscore-prefixed keywords (unlike C). -\item \tcode{universal_template} or similar would also work but again we don't often use underscore in keyworfs (though, \tcode{co_yield} and co do). +\item \tcode{universal_template} or similar would also work but again we don't often use underscore in keywords (though, \tcode{co_yield} and co do). \item \tcode{anytmplarg} or any such weird enough keyword to be unlikely to be used as identifier would also work. (we can't pick something non-weird, to not break existing code). @@ -526,37 +526,37 @@ \subsection{Syntax} > \end{colorblock} -Putting some of these options together show they are quite similar. - -\begin{table} -\tiny -\hspace{-30pt} -\begin{tabular}{c | c | c} -\begin{colorblock} -template < - universal template, - template auto C -> -struct s; -\end{colorblock} -& -\begin{colorblock} -template < - anytmplarg, - template auto C -> -struct s; -\end{colorblock} -& -\begin{colorblock} -template < - template auto, - template