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