1*06c3fb27SDimitry Andric // -*- C++ -*- 2*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 3*06c3fb27SDimitry Andric // 4*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*06c3fb27SDimitry Andric // 8*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 9*06c3fb27SDimitry Andric 10*06c3fb27SDimitry Andric #ifndef _LIBCPP___THREAD_ID_H 11*06c3fb27SDimitry Andric #define _LIBCPP___THREAD_ID_H 12*06c3fb27SDimitry Andric 13*06c3fb27SDimitry Andric #include <__compare/ordering.h> 14*06c3fb27SDimitry Andric #include <__config> 15*06c3fb27SDimitry Andric #include <__fwd/hash.h> 16*06c3fb27SDimitry Andric #include <__threading_support> 17*06c3fb27SDimitry Andric #include <iosfwd> 18*06c3fb27SDimitry Andric 19*06c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20*06c3fb27SDimitry Andric # pragma GCC system_header 21*06c3fb27SDimitry Andric #endif 22*06c3fb27SDimitry Andric 23*06c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 24*06c3fb27SDimitry Andric 25*06c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS 26*06c3fb27SDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI __thread_id; 27*06c3fb27SDimitry Andric 28*06c3fb27SDimitry Andric namespace this_thread { 29*06c3fb27SDimitry Andric 30*06c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI __thread_id get_id() _NOEXCEPT; 31*06c3fb27SDimitry Andric 32*06c3fb27SDimitry Andric } // namespace this_thread 33*06c3fb27SDimitry Andric 34*06c3fb27SDimitry Andric template <> 35*06c3fb27SDimitry Andric struct hash<__thread_id>; 36*06c3fb27SDimitry Andric 37*06c3fb27SDimitry Andric class _LIBCPP_TEMPLATE_VIS __thread_id { 38*06c3fb27SDimitry Andric // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 39*06c3fb27SDimitry Andric // NULL is the no-thread value on Darwin. Someone needs to check 40*06c3fb27SDimitry Andric // on other platforms. We assume 0 works everywhere for now. 41*06c3fb27SDimitry Andric __libcpp_thread_id __id_; 42*06c3fb27SDimitry Andric 43*06c3fb27SDimitry Andric static _LIBCPP_HIDE_FROM_ABI bool 44*06c3fb27SDimitry Andric __lt_impl(__thread_id __x, __thread_id __y) _NOEXCEPT { // id==0 is always less than any other thread_id 45*06c3fb27SDimitry Andric if (__x.__id_ == 0) 46*06c3fb27SDimitry Andric return __y.__id_ != 0; 47*06c3fb27SDimitry Andric if (__y.__id_ == 0) 48*06c3fb27SDimitry Andric return false; 49*06c3fb27SDimitry Andric return __libcpp_thread_id_less(__x.__id_, __y.__id_); 50*06c3fb27SDimitry Andric } 51*06c3fb27SDimitry Andric 52*06c3fb27SDimitry Andric public: 53*06c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI __thread_id() _NOEXCEPT : __id_(0) {} 54*06c3fb27SDimitry Andric 55*06c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI void __reset() { __id_ = 0; } 56*06c3fb27SDimitry Andric 57*06c3fb27SDimitry Andric friend _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT; 58*06c3fb27SDimitry Andric # if _LIBCPP_STD_VER <= 17 59*06c3fb27SDimitry Andric friend _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT; 60*06c3fb27SDimitry Andric # else // _LIBCPP_STD_VER <= 17 61*06c3fb27SDimitry Andric friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept; 62*06c3fb27SDimitry Andric # endif // _LIBCPP_STD_VER <= 17 63*06c3fb27SDimitry Andric 64*06c3fb27SDimitry Andric template <class _CharT, class _Traits> 65*06c3fb27SDimitry Andric friend _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 66*06c3fb27SDimitry Andric operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); 67*06c3fb27SDimitry Andric 68*06c3fb27SDimitry Andric private: 69*06c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 70*06c3fb27SDimitry Andric 71*06c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend __libcpp_thread_id __get_underlying_id(const __thread_id __id) { return __id.__id_; } 72*06c3fb27SDimitry Andric 73*06c3fb27SDimitry Andric friend __thread_id this_thread::get_id() _NOEXCEPT; 74*06c3fb27SDimitry Andric friend class _LIBCPP_EXPORTED_FROM_ABI thread; 75*06c3fb27SDimitry Andric friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; 76*06c3fb27SDimitry Andric }; 77*06c3fb27SDimitry Andric 78*06c3fb27SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT { 79*06c3fb27SDimitry Andric // Don't pass id==0 to underlying routines 80*06c3fb27SDimitry Andric if (__x.__id_ == 0) 81*06c3fb27SDimitry Andric return __y.__id_ == 0; 82*06c3fb27SDimitry Andric if (__y.__id_ == 0) 83*06c3fb27SDimitry Andric return false; 84*06c3fb27SDimitry Andric return __libcpp_thread_id_equal(__x.__id_, __y.__id_); 85*06c3fb27SDimitry Andric } 86*06c3fb27SDimitry Andric 87*06c3fb27SDimitry Andric # if _LIBCPP_STD_VER <= 17 88*06c3fb27SDimitry Andric 89*06c3fb27SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x == __y); } 90*06c3fb27SDimitry Andric 91*06c3fb27SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT { 92*06c3fb27SDimitry Andric return __thread_id::__lt_impl(__x.__id_, __y.__id_); 93*06c3fb27SDimitry Andric } 94*06c3fb27SDimitry Andric 95*06c3fb27SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__y < __x); } 96*06c3fb27SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator>(__thread_id __x, __thread_id __y) _NOEXCEPT { return __y < __x; } 97*06c3fb27SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x < __y); } 98*06c3fb27SDimitry Andric 99*06c3fb27SDimitry Andric # else // _LIBCPP_STD_VER <= 17 100*06c3fb27SDimitry Andric 101*06c3fb27SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept { 102*06c3fb27SDimitry Andric if (__x == __y) 103*06c3fb27SDimitry Andric return strong_ordering::equal; 104*06c3fb27SDimitry Andric if (__thread_id::__lt_impl(__x, __y)) 105*06c3fb27SDimitry Andric return strong_ordering::less; 106*06c3fb27SDimitry Andric return strong_ordering::greater; 107*06c3fb27SDimitry Andric } 108*06c3fb27SDimitry Andric 109*06c3fb27SDimitry Andric # endif // _LIBCPP_STD_VER <= 17 110*06c3fb27SDimitry Andric 111*06c3fb27SDimitry Andric namespace this_thread { 112*06c3fb27SDimitry Andric 113*06c3fb27SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI __thread_id get_id() _NOEXCEPT { return __libcpp_thread_get_current_id(); } 114*06c3fb27SDimitry Andric 115*06c3fb27SDimitry Andric } // namespace this_thread 116*06c3fb27SDimitry Andric 117*06c3fb27SDimitry Andric #endif // !_LIBCPP_HAS_NO_THREADS 118*06c3fb27SDimitry Andric 119*06c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD 120*06c3fb27SDimitry Andric 121*06c3fb27SDimitry Andric #endif // _LIBCPP___THREAD_ID_H 122