https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120649
Bug ID: 120649
Summary: Consider using pthread_gettid_np (or similar) for
std::thread:id
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: redi at gcc dot gnu.org
Target Milestone: ---
Glibc recently (in version 2.42) added pthread_gettid_np to get an integer
thread ID from an opaque pthread_t.
pid_t pthread_gettid_np(pthread_t)
https://sourceware.org/bugzilla/show_bug.cgi?id=27880
We could use that to make our std::thread::id comparisons and formatting more
robust.
Currently we have:
#if __cpp_lib_three_way_comparison
inline strong_ordering
operator<=>(thread::id __x, thread::id __y) noexcept
{ return __x._M_thread <=> __y._M_thread; }
#else
inline bool
operator!=(thread::id __x, thread::id __y) noexcept
{ return !(__x == __y); }
inline bool
operator<(thread::id __x, thread::id __y) noexcept
{
// Pthreads doesn't define any way to do this, so we just have to
// assume native_handle_type is LessThanComparable.
return __x._M_thread < __y._M_thread;
}
And for output:
template<class _CharT, class _Traits>
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
{
// Convert non-void pointers to const void* for formatted output.
using __output_type
= __conditional_t<is_pointer<thread::native_handle_type>::value,
const void*,
thread::native_handle_type>;
if (__id == thread::id())
return __out << "thread::id of a non-executing thread";
else
return __out << static_cast<__output_type>(__id._M_thread);
}
(and std::formatter<std::thread::id> is similar).
This works reasonably well for Glibc where pthread_t is a pointer, but it might
be preferable to output a TID instead of the pointer value. The pointers are
only useful to distinguish different threads, whereas a TID can be
cross-referenced with the thread ID visible in the process table.
Changing the comparisons might be an ABI change though, because two
std::thread::id values might compare differently in two objects compiled with
different versions of <=>.
Some other C libraries provide similar functionality for obtaining an integer
ID from the thread handle.
Bionic has the same API as Glibc, pid_t pthread_gettid_np(pthread_t t).
Darwin has int pthread_threadid_np(pthread_t thread, uint64_t *thread_id).
Windows has DWORD GetThreadId(HANDLE Thread) (although that won't help when we
use winpthreads unless we can get a HANDLE from a pthread_t).