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