1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP___THREADING_SUPPORT 11#define _LIBCPP___THREADING_SUPPORT 12 13#include <__availability> 14#include <__chrono/convert_to_timespec.h> 15#include <__chrono/duration.h> 16#include <__config> 17#include <__thread/poll_with_backoff.h> 18#include <errno.h> 19#include <iosfwd> 20#include <limits> 21 22#ifdef __MVS__ 23# include <__support/ibm/nanosleep.h> 24#endif 25 26#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 27# pragma GCC system_header 28#endif 29 30#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 31# include <__external_threading> 32#elif !defined(_LIBCPP_HAS_NO_THREADS) 33 34#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 35# include <pthread.h> 36# include <sched.h> 37#elif defined(_LIBCPP_HAS_THREAD_API_C11) 38# include <threads.h> 39#endif 40 41#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 42 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ 43 defined(_LIBCPP_HAS_THREAD_API_WIN32) 44#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 45#else 46#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 47#endif 48 49#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 50#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 51#else 52#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 53#endif 54 55typedef ::timespec __libcpp_timespec_t; 56#endif // !defined(_LIBCPP_HAS_NO_THREADS) 57 58_LIBCPP_BEGIN_NAMESPACE_STD 59 60#if !defined(_LIBCPP_HAS_NO_THREADS) 61 62#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 63// Mutex 64typedef pthread_mutex_t __libcpp_mutex_t; 65#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 66 67typedef pthread_mutex_t __libcpp_recursive_mutex_t; 68 69// Condition Variable 70typedef pthread_cond_t __libcpp_condvar_t; 71#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 72 73// Execute once 74typedef pthread_once_t __libcpp_exec_once_flag; 75#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 76 77// Thread id 78#if defined(__MVS__) 79 typedef unsigned long long __libcpp_thread_id; 80#else 81 typedef pthread_t __libcpp_thread_id; 82#endif 83 84// Thread 85#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t())) 86typedef pthread_t __libcpp_thread_t; 87 88// Thread Local Storage 89typedef pthread_key_t __libcpp_tls_key; 90 91#define _LIBCPP_TLS_DESTRUCTOR_CC 92#elif defined(_LIBCPP_HAS_THREAD_API_C11) 93// Mutex 94typedef mtx_t __libcpp_mutex_t; 95// mtx_t is a struct so using {} for initialization is valid. 96#define _LIBCPP_MUTEX_INITIALIZER {} 97 98typedef mtx_t __libcpp_recursive_mutex_t; 99 100// Condition Variable 101typedef cnd_t __libcpp_condvar_t; 102// cnd_t is a struct so using {} for initialization is valid. 103#define _LIBCPP_CONDVAR_INITIALIZER {} 104 105// Execute once 106typedef once_flag __libcpp_exec_once_flag; 107#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT 108 109// Thread id 110typedef thrd_t __libcpp_thread_id; 111 112// Thread 113#define _LIBCPP_NULL_THREAD 0U 114 115typedef thrd_t __libcpp_thread_t; 116 117// Thread Local Storage 118typedef tss_t __libcpp_tls_key; 119 120#define _LIBCPP_TLS_DESTRUCTOR_CC 121#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 122// Mutex 123typedef void* __libcpp_mutex_t; 124#define _LIBCPP_MUTEX_INITIALIZER 0 125 126#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 127typedef void* __libcpp_recursive_mutex_t[6]; 128#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 129typedef void* __libcpp_recursive_mutex_t[5]; 130#else 131# error Unsupported architecture 132#endif 133 134// Condition Variable 135typedef void* __libcpp_condvar_t; 136#define _LIBCPP_CONDVAR_INITIALIZER 0 137 138// Execute Once 139typedef void* __libcpp_exec_once_flag; 140#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 141 142// Thread ID 143typedef long __libcpp_thread_id; 144 145// Thread 146#define _LIBCPP_NULL_THREAD 0U 147 148typedef void* __libcpp_thread_t; 149 150// Thread Local Storage 151typedef long __libcpp_tls_key; 152 153#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 154#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 155 156#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 157// Mutex 158_LIBCPP_THREAD_ABI_VISIBILITY 159int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 160 161_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 162int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 163 164_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 165bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 166 167_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 168int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 169 170_LIBCPP_THREAD_ABI_VISIBILITY 171int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 172 173_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 174int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 175 176_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 177bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 178 179_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 180int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 181 182_LIBCPP_THREAD_ABI_VISIBILITY 183int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 184 185// Condition variable 186_LIBCPP_THREAD_ABI_VISIBILITY 187int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 188 189_LIBCPP_THREAD_ABI_VISIBILITY 190int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 191 192_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 193int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 194 195_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 196int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 197 __libcpp_timespec_t *__ts); 198 199_LIBCPP_THREAD_ABI_VISIBILITY 200int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 201 202// Execute once 203_LIBCPP_THREAD_ABI_VISIBILITY 204int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 205 void (*__init_routine)()); 206 207// Thread id 208_LIBCPP_THREAD_ABI_VISIBILITY 209bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2); 210 211_LIBCPP_THREAD_ABI_VISIBILITY 212bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2); 213 214// Thread 215_LIBCPP_THREAD_ABI_VISIBILITY 216bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 217 218_LIBCPP_THREAD_ABI_VISIBILITY 219int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 220 void *__arg); 221 222_LIBCPP_THREAD_ABI_VISIBILITY 223__libcpp_thread_id __libcpp_thread_get_current_id(); 224 225_LIBCPP_THREAD_ABI_VISIBILITY 226__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 227 228_LIBCPP_THREAD_ABI_VISIBILITY 229int __libcpp_thread_join(__libcpp_thread_t *__t); 230 231_LIBCPP_THREAD_ABI_VISIBILITY 232int __libcpp_thread_detach(__libcpp_thread_t *__t); 233 234_LIBCPP_THREAD_ABI_VISIBILITY 235void __libcpp_thread_yield(); 236 237_LIBCPP_THREAD_ABI_VISIBILITY 238void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 239 240// Thread local storage 241_LIBCPP_THREAD_ABI_VISIBILITY 242int __libcpp_tls_create(__libcpp_tls_key* __key, 243 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 244 245_LIBCPP_THREAD_ABI_VISIBILITY 246void *__libcpp_tls_get(__libcpp_tls_key __key); 247 248_LIBCPP_THREAD_ABI_VISIBILITY 249int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 250 251#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 252 253#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 254 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) 255 256#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 257 258int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 259{ 260 pthread_mutexattr_t attr; 261 int __ec = pthread_mutexattr_init(&attr); 262 if (__ec) 263 return __ec; 264 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 265 if (__ec) { 266 pthread_mutexattr_destroy(&attr); 267 return __ec; 268 } 269 __ec = pthread_mutex_init(__m, &attr); 270 if (__ec) { 271 pthread_mutexattr_destroy(&attr); 272 return __ec; 273 } 274 __ec = pthread_mutexattr_destroy(&attr); 275 if (__ec) { 276 pthread_mutex_destroy(__m); 277 return __ec; 278 } 279 return 0; 280} 281 282int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 283{ 284 return pthread_mutex_lock(__m); 285} 286 287bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 288{ 289 return pthread_mutex_trylock(__m) == 0; 290} 291 292int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 293{ 294 return pthread_mutex_unlock(__m); 295} 296 297int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 298{ 299 return pthread_mutex_destroy(__m); 300} 301 302int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 303{ 304 return pthread_mutex_lock(__m); 305} 306 307bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 308{ 309 return pthread_mutex_trylock(__m) == 0; 310} 311 312int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 313{ 314 return pthread_mutex_unlock(__m); 315} 316 317int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 318{ 319 return pthread_mutex_destroy(__m); 320} 321 322// Condition Variable 323int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 324{ 325 return pthread_cond_signal(__cv); 326} 327 328int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 329{ 330 return pthread_cond_broadcast(__cv); 331} 332 333int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 334{ 335 return pthread_cond_wait(__cv, __m); 336} 337 338int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 339 __libcpp_timespec_t *__ts) 340{ 341 return pthread_cond_timedwait(__cv, __m, __ts); 342} 343 344int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 345{ 346 return pthread_cond_destroy(__cv); 347} 348 349// Execute once 350int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 351 void (*__init_routine)()) { 352 return pthread_once(__flag, __init_routine); 353} 354 355// Thread id 356// Returns non-zero if the thread ids are equal, otherwise 0 357bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) 358{ 359 return __t1 == __t2; 360} 361 362// Returns non-zero if t1 < t2, otherwise 0 363bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) 364{ 365 return __t1 < __t2; 366} 367 368// Thread 369bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 370 return __libcpp_thread_get_id(__t) == 0; 371} 372 373int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 374 void *__arg) 375{ 376 return pthread_create(__t, nullptr, __func, __arg); 377} 378 379__libcpp_thread_id __libcpp_thread_get_current_id() 380{ 381 const __libcpp_thread_t thread = pthread_self(); 382 return __libcpp_thread_get_id(&thread); 383} 384 385__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 386{ 387#if defined(__MVS__) 388 return __t->__; 389#else 390 return *__t; 391#endif 392} 393 394int __libcpp_thread_join(__libcpp_thread_t *__t) 395{ 396 return pthread_join(*__t, nullptr); 397} 398 399int __libcpp_thread_detach(__libcpp_thread_t *__t) 400{ 401 return pthread_detach(*__t); 402} 403 404void __libcpp_thread_yield() 405{ 406 sched_yield(); 407} 408 409void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 410{ 411 __libcpp_timespec_t __ts = _VSTD::__convert_to_timespec<__libcpp_timespec_t>(__ns); 412 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 413} 414 415// Thread local storage 416int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 417{ 418 return pthread_key_create(__key, __at_exit); 419} 420 421void *__libcpp_tls_get(__libcpp_tls_key __key) 422{ 423 return pthread_getspecific(__key); 424} 425 426int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 427{ 428 return pthread_setspecific(__key, __p); 429} 430 431#elif defined(_LIBCPP_HAS_THREAD_API_C11) 432 433int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 434{ 435 return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; 436} 437 438int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 439{ 440 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 441} 442 443bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 444{ 445 return mtx_trylock(__m) == thrd_success; 446} 447 448int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 449{ 450 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 451} 452 453int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 454{ 455 mtx_destroy(__m); 456 return 0; 457} 458 459int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 460{ 461 return mtx_lock(__m) == thrd_success ? 0 : EINVAL; 462} 463 464bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 465{ 466 return mtx_trylock(__m) == thrd_success; 467} 468 469int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 470{ 471 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; 472} 473 474int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 475{ 476 mtx_destroy(__m); 477 return 0; 478} 479 480// Condition Variable 481int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 482{ 483 return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; 484} 485 486int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 487{ 488 return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; 489} 490 491int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 492{ 493 return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; 494} 495 496int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 497 timespec *__ts) 498{ 499 int __ec = cnd_timedwait(__cv, __m, __ts); 500 return __ec == thrd_timedout ? ETIMEDOUT : __ec; 501} 502 503int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 504{ 505 cnd_destroy(__cv); 506 return 0; 507} 508 509// Execute once 510int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 511 void (*init_routine)(void)) { 512 ::call_once(flag, init_routine); 513 return 0; 514} 515 516// Thread id 517// Returns non-zero if the thread ids are equal, otherwise 0 518bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 519{ 520 return thrd_equal(t1, t2) != 0; 521} 522 523// Returns non-zero if t1 < t2, otherwise 0 524bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 525{ 526 return t1 < t2; 527} 528 529// Thread 530bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 531 return __libcpp_thread_get_id(__t) == 0; 532} 533 534int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 535 void *__arg) 536{ 537 int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); 538 return __ec == thrd_nomem ? ENOMEM : __ec; 539} 540 541__libcpp_thread_id __libcpp_thread_get_current_id() 542{ 543 return thrd_current(); 544} 545 546__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 547{ 548 return *__t; 549} 550 551int __libcpp_thread_join(__libcpp_thread_t *__t) 552{ 553 return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; 554} 555 556int __libcpp_thread_detach(__libcpp_thread_t *__t) 557{ 558 return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; 559} 560 561void __libcpp_thread_yield() 562{ 563 thrd_yield(); 564} 565 566void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 567{ 568 __libcpp_timespec_t __ts = _VSTD::__convert_to_timespec<__libcpp_timespec_t>(__ns); 569 thrd_sleep(&__ts, nullptr); 570} 571 572// Thread local storage 573int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 574{ 575 return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; 576} 577 578void *__libcpp_tls_get(__libcpp_tls_key __key) 579{ 580 return tss_get(__key); 581} 582 583int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 584{ 585 return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; 586} 587 588#endif 589 590 591#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 592 593class _LIBCPP_TYPE_VIS thread; 594class _LIBCPP_TYPE_VIS __thread_id; 595 596namespace this_thread 597{ 598 599_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 600 601} // namespace this_thread 602 603template<> struct hash<__thread_id>; 604 605class _LIBCPP_TEMPLATE_VIS __thread_id 606{ 607 // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 608 // NULL is the no-thread value on Darwin. Someone needs to check 609 // on other platforms. We assume 0 works everywhere for now. 610 __libcpp_thread_id __id_; 611 612public: 613 _LIBCPP_INLINE_VISIBILITY 614 __thread_id() _NOEXCEPT : __id_(0) {} 615 616 friend _LIBCPP_INLINE_VISIBILITY 617 bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 618 { // don't pass id==0 to underlying routines 619 if (__x.__id_ == 0) return __y.__id_ == 0; 620 if (__y.__id_ == 0) return false; 621 return __libcpp_thread_id_equal(__x.__id_, __y.__id_); 622 } 623 friend _LIBCPP_INLINE_VISIBILITY 624 bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 625 {return !(__x == __y);} 626 friend _LIBCPP_INLINE_VISIBILITY 627 bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 628 { // id==0 is always less than any other thread_id 629 if (__x.__id_ == 0) return __y.__id_ != 0; 630 if (__y.__id_ == 0) return false; 631 return __libcpp_thread_id_less(__x.__id_, __y.__id_); 632 } 633 friend _LIBCPP_INLINE_VISIBILITY 634 bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 635 {return !(__y < __x);} 636 friend _LIBCPP_INLINE_VISIBILITY 637 bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 638 {return __y < __x ;} 639 friend _LIBCPP_INLINE_VISIBILITY 640 bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 641 {return !(__x < __y);} 642 643 _LIBCPP_INLINE_VISIBILITY 644 void __reset() { __id_ = 0; } 645 646 template<class _CharT, class _Traits> 647 friend 648 _LIBCPP_INLINE_VISIBILITY 649 basic_ostream<_CharT, _Traits>& 650 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); 651 652private: 653 _LIBCPP_INLINE_VISIBILITY 654 __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 655 656 friend __thread_id this_thread::get_id() _NOEXCEPT; 657 friend class _LIBCPP_TYPE_VIS thread; 658 friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; 659}; 660 661namespace this_thread 662{ 663 664inline _LIBCPP_INLINE_VISIBILITY 665__thread_id 666get_id() _NOEXCEPT 667{ 668 return __libcpp_thread_get_current_id(); 669} 670 671} // namespace this_thread 672 673#endif // !_LIBCPP_HAS_NO_THREADS 674 675_LIBCPP_END_NAMESPACE_STD 676 677#endif // _LIBCPP___THREADING_SUPPORT 678