[libcxx-commits] [libcxx] [libc++] Consolidate ordering/hashing/formatting of std::thread::id. (PR #195763)
Alexey Samsonov via libcxx-commits
libcxx-commits at lists.llvm.org
Mon May 4 22:54:19 PDT 2026
https://github.com/vonosmas updated https://github.com/llvm/llvm-project/pull/195763
>From 849aa7f9685bcda534cd26601fc0a8e43e18322b Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Tue, 5 May 2026 00:07:53 +0000
Subject: [PATCH 1/4] [libc++] Consolidate ordering/hashing/formatting of
std::thread::id.
In practice, libc++ assumes that the internal type backing the
std::thread::id is either pointer, or an integral type. Also, despite
the implementation-specific definitions (for C11, pthreads, Windows),
this type may be left unspecified, as different POSIX systems define
pthread_t in a different way.
Consolidate all the type-dependent logic for computing std::hash,
specifying std::formatter behavior, and implementing operator<=> for
std::thread::id in the class itself, together with all the assertions
about the underlying types. This should hopefully make the code cleaner,
and clearly indicate which parts need to be extended if/when new types
of thread-id need to be supported.
An alternative to that would be sinking the conditional logic for
comparing/formatting/hashing these IDs into the __thread/support
headers, which was attempted initially. The downsides to these would
be both duplication of the boilerplate code *and* the conditional
code (as pointer/integer distinction and type-traits would need to be
copied both to pthreads, and to C11 implementation).
---
libcxx/include/__thread/formatter.h | 25 +------
libcxx/include/__thread/id.h | 87 +++++++++++++++++------
libcxx/include/__thread/support.h | 3 -
libcxx/include/__thread/support/c11.h | 10 ---
libcxx/include/__thread/support/pthread.h | 10 ---
libcxx/include/__thread/thread.h | 2 +-
6 files changed, 68 insertions(+), 69 deletions(-)
diff --git a/libcxx/include/__thread/formatter.h b/libcxx/include/__thread/formatter.h
index 826607d47b469..352b588c2f923 100644
--- a/libcxx/include/__thread/formatter.h
+++ b/libcxx/include/__thread/formatter.h
@@ -18,10 +18,6 @@
#include <__format/formatter_integral.h>
#include <__format/parser_std_format_spec.h>
#include <__thread/id.h>
-#include <__type_traits/conditional.h>
-#include <__type_traits/is_pointer.h>
-#include <__type_traits/is_same.h>
-#include <cstdint>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -43,29 +39,12 @@ struct formatter<__thread_id, _CharT> {
template <class _FormatContext>
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(__thread_id __id, _FormatContext& __ctx) const {
- // In __thread/support/pthread.h, __libcpp_thread_id is either a
- // unsigned long long or a pthread_t.
- //
- // The type of pthread_t is left unspecified in POSIX so it can be any
- // type. The most logical types are an integral or pointer.
- // On Linux systems pthread_t is an unsigned long long.
- // On Apple systems pthread_t is a pointer type.
- //
- // Note the output should match what the stream operator does. Since
- // the ostream operator has been shipped years before this formatter
- // was added to the Standard, this formatter does what the stream
- // operator does. This may require platform specific changes.
-
- using _Tp = decltype(__get_underlying_id(__id));
- using _Cp = conditional_t<integral<_Tp>, _Tp, conditional_t<is_pointer_v<_Tp>, uintptr_t, void>>;
- static_assert(!is_same_v<_Cp, void>, "unsupported thread::id type, please file a bug report");
-
__format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx);
- if constexpr (is_pointer_v<_Tp>) {
+ if constexpr (__thread_id::__PRINT_AS_HEX) {
__specs.__std_.__alternate_form_ = true;
__specs.__std_.__type_ = __format_spec::__type::__hexadecimal_lower_case;
}
- return __formatter::__format_integer(reinterpret_cast<_Cp>(__get_underlying_id(__id)), __ctx, __specs);
+ return __formatter::__format_integer(__id.__get_formatter_value(), __ctx, __specs);
}
__format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__right};
diff --git a/libcxx/include/__thread/id.h b/libcxx/include/__thread/id.h
index 14a51fc9ee880..f19aa4ad7c11f 100644
--- a/libcxx/include/__thread/id.h
+++ b/libcxx/include/__thread/id.h
@@ -15,6 +15,10 @@
#include <__fwd/functional.h>
#include <__fwd/ostream.h>
#include <__thread/support.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/is_integral.h>
+#include <__type_traits/is_pointer.h>
+#include <cstdint>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -35,24 +39,67 @@ template <>
struct hash<__thread_id>;
class __thread_id {
- // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
- // NULL is the no-thread value on Darwin. Someone needs to check
- // on other platforms. We assume 0 works everywhere for now.
__libcpp_thread_id __id_;
- static _LIBCPP_HIDE_FROM_ABI bool
- __lt_impl(__thread_id __x, __thread_id __y) _NOEXCEPT { // id==0 is always less than any other thread_id
- if (__x.__id_ == 0)
- return __y.__id_ != 0;
- if (__y.__id_ == 0)
- return false;
- return __libcpp_thread_id_less(__x.__id_, __y.__id_);
+ // Even though __libcpp_thread_id is provided by underlying threading implementation
+ // (e.g. C11, pthreads, or Windows) its type may still be unspecified. E.g. for pthreads
+ // implementation __libcpp_thread_id is an alias for pthread_t, which is left unspecified
+ // in POSIX. Typically it's either an integral type (glibc) or a pointer (Apple systems),
+ // but it can also be an opaque type on some systems / libc implementations.
+ //
+ // Note that in order to satisfy standard requirements on std::thread::id, we need:
+ // * strong total order
+ // * formatter support
+ // * std::hash implementation
+ // Currently, we can implement all of the above only on pointer and integral types.
+ using _Tp = __libcpp_thread_id;
+ static_assert(is_pointer_v<_Tp> || is_integral_v<_Tp>, "unsupported thread::id type, please file a bug report");
+
+ // Strong total order implementation.
+ // Here we provide a best-effort implementation of strong total order, comparing
+ // integral types as-is and routing pointers through uintptr_t for a well-defined comparison.
+ static _LIBCPP_HIDE_FROM_ABI bool __eq_impl(__thread_id __x, __thread_id __y) _NOEXCEPT {
+ if constexpr (is_pointer_v<_Tp>) {
+ return reinterpret_cast<uintptr_t>(__x.__id_) == reinterpret_cast<uintptr_t>(__y.__id_);
+ } else {
+ return __x.__id_ == __y.__id_;
+ }
}
+ static _LIBCPP_HIDE_FROM_ABI bool __lt_impl(__thread_id __x, __thread_id __y) _NOEXCEPT {
+ if constexpr (is_pointer_v<_Tp>) {
+ return reinterpret_cast<uintptr_t>(__x.__id_) < reinterpret_cast<uintptr_t>(__y.__id_);
+ } else {
+ // For integral thread IDs, assume 0 is always less than any other thread_id.
+ if (__x.__id_ == 0)
+ return __y.__id_ != 0;
+ if (__y.__id_ == 0)
+ return false;
+ return __x.__id_ < __y.__id_;
+ }
+ }
+
+ // Hashing implementation.
+ // Simply use the underlying pointer or integral types as-is.
+ using _HashTp = _Tp;
+ _LIBCPP_HIDE_FROM_ABI _HashTp __hash_value() const { return __id_; }
+
+ // Formatter implementation.
+ // Note the output should match what the stream operator does. Since
+ // the ostream operator has been shipped years before the formatter
+ // was added to the Standard, our logic mimics what the stream
+ // operator does (i.e. prints thread-id as integer, but uses a hexadecimal
+ // format if it's represented by a pointer)
+ using _FormatterTp = conditional_t<is_integral_v<_Tp>, _Tp, uintptr_t>;
+
+ static _LIBCPP_HIDE_FROM_ABI constexpr bool __PRINT_AS_HEX = is_pointer_v<_Tp>;
+
+ _LIBCPP_HIDE_FROM_ABI _FormatterTp __get_formatter_value() const { return reinterpret_cast<_FormatterTp>(__id_); }
+
public:
- _LIBCPP_HIDE_FROM_ABI __thread_id() _NOEXCEPT : __id_(0) {}
+ _LIBCPP_HIDE_FROM_ABI __thread_id() _NOEXCEPT : __id_{} {}
- _LIBCPP_HIDE_FROM_ABI void __reset() { __id_ = 0; }
+ _LIBCPP_HIDE_FROM_ABI void __reset() { __id_ = __libcpp_thread_id{}; }
friend _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT;
# if _LIBCPP_STD_VER <= 17
@@ -66,22 +113,18 @@ class __thread_id {
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
private:
- _LIBCPP_HIDE_FROM_ABI __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
-
- _LIBCPP_HIDE_FROM_ABI friend __libcpp_thread_id __get_underlying_id(const __thread_id __id) { return __id.__id_; }
+ _LIBCPP_HIDE_FROM_ABI __thread_id(__libcpp_thread_id __id) : __id_{__id} {}
friend __thread_id this_thread::get_id() _NOEXCEPT;
friend class _LIBCPP_EXPORTED_FROM_ABI thread;
friend struct hash<__thread_id>;
+
+ template <class _Typename, class _CharT>
+ friend struct formatter;
};
inline _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT {
- // Don't pass id==0 to underlying routines
- if (__x.__id_ == 0)
- return __y.__id_ == 0;
- if (__y.__id_ == 0)
- return false;
- return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
+ return __thread_id::__eq_impl(__x, __y);
}
# if _LIBCPP_STD_VER <= 17
@@ -89,7 +132,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _
inline _LIBCPP_HIDE_FROM_ABI bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x == __y); }
inline _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT {
- return __thread_id::__lt_impl(__x.__id_, __y.__id_);
+ return __thread_id::__lt_impl(__x, __y);
}
inline _LIBCPP_HIDE_FROM_ABI bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__y < __x); }
diff --git a/libcxx/include/__thread/support.h b/libcxx/include/__thread/support.h
index 50a18daf2b685..62b336ea5f429 100644
--- a/libcxx/include/__thread/support.h
+++ b/libcxx/include/__thread/support.h
@@ -72,9 +72,6 @@ int __libcpp_execute_once(__libcpp_exec_once_flag*, void (*__init_routine)());
//
using __libcpp_thread_id = ...;
-bool __libcpp_thread_id_equal(__libcpp_thread_id, __libcpp_thread_id);
-bool __libcpp_thread_id_less(__libcpp_thread_id, __libcpp_thread_id);
-
//
// Thread
//
diff --git a/libcxx/include/__thread/support/c11.h b/libcxx/include/__thread/support/c11.h
index 463c8496ba6f4..5118467880a96 100644
--- a/libcxx/include/__thread/support/c11.h
+++ b/libcxx/include/__thread/support/c11.h
@@ -124,16 +124,6 @@ inline _LIBCPP_HIDE_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag*
//
typedef thrd_t __libcpp_thread_id;
-// Returns non-zero if the thread ids are equal, otherwise 0
-inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) {
- return thrd_equal(t1, t2) != 0;
-}
-
-// Returns non-zero if t1 < t2, otherwise 0
-inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) {
- return t1 < t2;
-}
-
//
// Thread
//
diff --git a/libcxx/include/__thread/support/pthread.h b/libcxx/include/__thread/support/pthread.h
index 4cf5c0342467b..faa5941b9c840 100644
--- a/libcxx/include/__thread/support/pthread.h
+++ b/libcxx/include/__thread/support/pthread.h
@@ -150,16 +150,6 @@ typedef unsigned long long __libcpp_thread_id;
typedef pthread_t __libcpp_thread_id;
#endif
-// Returns non-zero if the thread ids are equal, otherwise 0
-inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) {
- return __t1 == __t2;
-}
-
-// Returns non-zero if t1 < t2, otherwise 0
-inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) {
- return __t1 < __t2;
-}
-
//
// Thread
//
diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h
index 7342cbb5e37f6..74017867b03df 100644
--- a/libcxx/include/__thread/thread.h
+++ b/libcxx/include/__thread/thread.h
@@ -123,7 +123,7 @@ void __thread_specific_ptr<_Tp>::set_pointer(pointer __p) {
template <>
struct hash<__thread_id> : public __unary_function<__thread_id, size_t> {
_LIBCPP_HIDE_FROM_ABI size_t operator()(__thread_id __v) const _NOEXCEPT {
- return hash<__libcpp_thread_id>()(__v.__id_);
+ return hash<__thread_id::_HashTp>()(__v.__hash_value());
}
};
>From 9d79d1d1b65a7ff0beb2f5a4eb86182640f4fd71 Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Tue, 5 May 2026 04:43:53 +0000
Subject: [PATCH 2/4] Support pre-C++17 mode, and remove unnecessary functions
from Windows header as well.
---
libcxx/include/__thread/id.h | 11 ++++++-----
libcxx/include/__thread/support/windows.h | 4 ----
libcxx/src/support/win32/thread_win32.cpp | 1 +
3 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/libcxx/include/__thread/id.h b/libcxx/include/__thread/id.h
index f19aa4ad7c11f..a52a525da839c 100644
--- a/libcxx/include/__thread/id.h
+++ b/libcxx/include/__thread/id.h
@@ -53,13 +53,14 @@ class __thread_id {
// * std::hash implementation
// Currently, we can implement all of the above only on pointer and integral types.
using _Tp = __libcpp_thread_id;
- static_assert(is_pointer_v<_Tp> || is_integral_v<_Tp>, "unsupported thread::id type, please file a bug report");
+ static_assert(is_pointer<_Tp>::value || is_integral<_Tp>::value,
+ "unsupported thread::id type, please file a bug report");
// Strong total order implementation.
// Here we provide a best-effort implementation of strong total order, comparing
// integral types as-is and routing pointers through uintptr_t for a well-defined comparison.
static _LIBCPP_HIDE_FROM_ABI bool __eq_impl(__thread_id __x, __thread_id __y) _NOEXCEPT {
- if constexpr (is_pointer_v<_Tp>) {
+ if _LIBCPP_CONSTEXPR (is_pointer<_Tp>::value) {
return reinterpret_cast<uintptr_t>(__x.__id_) == reinterpret_cast<uintptr_t>(__y.__id_);
} else {
return __x.__id_ == __y.__id_;
@@ -67,7 +68,7 @@ class __thread_id {
}
static _LIBCPP_HIDE_FROM_ABI bool __lt_impl(__thread_id __x, __thread_id __y) _NOEXCEPT {
- if constexpr (is_pointer_v<_Tp>) {
+ if _LIBCPP_CONSTEXPR (is_pointer<_Tp>::value) {
return reinterpret_cast<uintptr_t>(__x.__id_) < reinterpret_cast<uintptr_t>(__y.__id_);
} else {
// For integral thread IDs, assume 0 is always less than any other thread_id.
@@ -90,9 +91,9 @@ class __thread_id {
// was added to the Standard, our logic mimics what the stream
// operator does (i.e. prints thread-id as integer, but uses a hexadecimal
// format if it's represented by a pointer)
- using _FormatterTp = conditional_t<is_integral_v<_Tp>, _Tp, uintptr_t>;
+ using _FormatterTp = conditional<is_integral<_Tp>::value, _Tp, uintptr_t>::type;
- static _LIBCPP_HIDE_FROM_ABI constexpr bool __PRINT_AS_HEX = is_pointer_v<_Tp>;
+ static _LIBCPP_CONSTEXPR const bool __PRINT_AS_HEX = is_pointer<_Tp>::value;
_LIBCPP_HIDE_FROM_ABI _FormatterTp __get_formatter_value() const { return reinterpret_cast<_FormatterTp>(__id_); }
diff --git a/libcxx/include/__thread/support/windows.h b/libcxx/include/__thread/support/windows.h
index 558b5c81dc191..e9f72ed9a9a7d 100644
--- a/libcxx/include/__thread/support/windows.h
+++ b/libcxx/include/__thread/support/windows.h
@@ -86,10 +86,6 @@ _LIBCPP_EXPORTED_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* __f
//
typedef long __libcpp_thread_id;
-_LIBCPP_EXPORTED_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2);
-
-_LIBCPP_EXPORTED_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2);
-
//
// Thread
//
diff --git a/libcxx/src/support/win32/thread_win32.cpp b/libcxx/src/support/win32/thread_win32.cpp
index 3a67d759f0f5e..734e173a40f40 100644
--- a/libcxx/src/support/win32/thread_win32.cpp
+++ b/libcxx/src/support/win32/thread_win32.cpp
@@ -135,6 +135,7 @@ int __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine
}
// Thread ID
+// TODO: Clarify whether to keep these functions since they were _LIBCPP_EXPORTED_FROM_ABI.
bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) { return __lhs == __rhs; }
bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) { return __lhs < __rhs; }
>From 8f2b26c26e38c9164a0aa02075aa40bdda65d003 Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Tue, 5 May 2026 05:13:58 +0000
Subject: [PATCH 3/4] Remove if-constexpr to support c++11
---
libcxx/include/__thread/id.h | 36 +++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/libcxx/include/__thread/id.h b/libcxx/include/__thread/id.h
index a52a525da839c..1a990c796f3bc 100644
--- a/libcxx/include/__thread/id.h
+++ b/libcxx/include/__thread/id.h
@@ -59,25 +59,27 @@ class __thread_id {
// Strong total order implementation.
// Here we provide a best-effort implementation of strong total order, comparing
// integral types as-is and routing pointers through uintptr_t for a well-defined comparison.
- static _LIBCPP_HIDE_FROM_ABI bool __eq_impl(__thread_id __x, __thread_id __y) _NOEXCEPT {
- if _LIBCPP_CONSTEXPR (is_pointer<_Tp>::value) {
- return reinterpret_cast<uintptr_t>(__x.__id_) == reinterpret_cast<uintptr_t>(__y.__id_);
- } else {
- return __x.__id_ == __y.__id_;
- }
+ template <typename Thr, enable_if<is_pointer<typename Thr::_Tp>::value, int>::type = 0>
+ static _LIBCPP_HIDE_FROM_ABI bool __eq_impl(Thr __x, Thr __y) _NOEXCEPT {
+ return reinterpret_cast<uintptr_t>(__x.__id_) == reinterpret_cast<uintptr_t>(__y.__id_);
+ }
+ template <typename Thr, enable_if<is_integral<typename Thr::_Tp>::value, int>::type = 0>
+ static _LIBCPP_HIDE_FROM_ABI bool __eq_impl(Thr __x, Thr __y) _NOEXCEPT {
+ return __x.__id_ == __y.__id_;
}
- static _LIBCPP_HIDE_FROM_ABI bool __lt_impl(__thread_id __x, __thread_id __y) _NOEXCEPT {
- if _LIBCPP_CONSTEXPR (is_pointer<_Tp>::value) {
- return reinterpret_cast<uintptr_t>(__x.__id_) < reinterpret_cast<uintptr_t>(__y.__id_);
- } else {
- // For integral thread IDs, assume 0 is always less than any other thread_id.
- if (__x.__id_ == 0)
- return __y.__id_ != 0;
- if (__y.__id_ == 0)
- return false;
- return __x.__id_ < __y.__id_;
- }
+ template <typename Thr, enable_if<is_pointer<typename Thr::_Tp>::value, int>::type = 0>
+ static _LIBCPP_HIDE_FROM_ABI bool __lt_impl(Thr __x, Thr __y) _NOEXCEPT {
+ return reinterpret_cast<uintptr_t>(__x.__id_) < reinterpret_cast<uintptr_t>(__y.__id_);
+ }
+ template <typename Thr, enable_if<is_integral<typename Thr::_Tp>::value, int>::type = 0>
+ static _LIBCPP_HIDE_FROM_ABI bool __lt_impl(Thr __x, Thr __y) _NOEXCEPT {
+ // For integral thread IDs, assume 0 is always less than any other thread_id.
+ if (__x.__id_ == 0)
+ return __y.__id_ != 0;
+ if (__y.__id_ == 0)
+ return false;
+ return __x.__id_ < __y.__id_;
}
// Hashing implementation.
>From 3e389d4d0daac123337fc1814c18725d12645440 Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Tue, 5 May 2026 05:53:48 +0000
Subject: [PATCH 4/4] More fixes for gcc and older c++ standards.
---
libcxx/include/__thread/id.h | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/libcxx/include/__thread/id.h b/libcxx/include/__thread/id.h
index 1a990c796f3bc..e925d2660005b 100644
--- a/libcxx/include/__thread/id.h
+++ b/libcxx/include/__thread/id.h
@@ -59,20 +59,20 @@ class __thread_id {
// Strong total order implementation.
// Here we provide a best-effort implementation of strong total order, comparing
// integral types as-is and routing pointers through uintptr_t for a well-defined comparison.
- template <typename Thr, enable_if<is_pointer<typename Thr::_Tp>::value, int>::type = 0>
+ template <typename Thr, typename enable_if<is_pointer<typename Thr::_Tp>::value, int>::type = 0>
static _LIBCPP_HIDE_FROM_ABI bool __eq_impl(Thr __x, Thr __y) _NOEXCEPT {
return reinterpret_cast<uintptr_t>(__x.__id_) == reinterpret_cast<uintptr_t>(__y.__id_);
}
- template <typename Thr, enable_if<is_integral<typename Thr::_Tp>::value, int>::type = 0>
+ template <typename Thr, typename enable_if<is_integral<typename Thr::_Tp>::value, int>::type = 0>
static _LIBCPP_HIDE_FROM_ABI bool __eq_impl(Thr __x, Thr __y) _NOEXCEPT {
return __x.__id_ == __y.__id_;
}
- template <typename Thr, enable_if<is_pointer<typename Thr::_Tp>::value, int>::type = 0>
+ template <typename Thr, typename enable_if<is_pointer<typename Thr::_Tp>::value, int>::type = 0>
static _LIBCPP_HIDE_FROM_ABI bool __lt_impl(Thr __x, Thr __y) _NOEXCEPT {
return reinterpret_cast<uintptr_t>(__x.__id_) < reinterpret_cast<uintptr_t>(__y.__id_);
}
- template <typename Thr, enable_if<is_integral<typename Thr::_Tp>::value, int>::type = 0>
+ template <typename Thr, typename enable_if<is_integral<typename Thr::_Tp>::value, int>::type = 0>
static _LIBCPP_HIDE_FROM_ABI bool __lt_impl(Thr __x, Thr __y) _NOEXCEPT {
// For integral thread IDs, assume 0 is always less than any other thread_id.
if (__x.__id_ == 0)
@@ -100,9 +100,9 @@ class __thread_id {
_LIBCPP_HIDE_FROM_ABI _FormatterTp __get_formatter_value() const { return reinterpret_cast<_FormatterTp>(__id_); }
public:
- _LIBCPP_HIDE_FROM_ABI __thread_id() _NOEXCEPT : __id_{} {}
+ _LIBCPP_HIDE_FROM_ABI __thread_id() _NOEXCEPT : __id_(__libcpp_thread_id()) {}
- _LIBCPP_HIDE_FROM_ABI void __reset() { __id_ = __libcpp_thread_id{}; }
+ _LIBCPP_HIDE_FROM_ABI void __reset() { __id_ = __libcpp_thread_id(); }
friend _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT;
# if _LIBCPP_STD_VER <= 17
@@ -116,7 +116,7 @@ class __thread_id {
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
private:
- _LIBCPP_HIDE_FROM_ABI __thread_id(__libcpp_thread_id __id) : __id_{__id} {}
+ _LIBCPP_HIDE_FROM_ABI __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
friend __thread_id this_thread::get_id() _NOEXCEPT;
friend class _LIBCPP_EXPORTED_FROM_ABI thread;
More information about the libcxx-commits
mailing list