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