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).

Reply via email to