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