2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP_THREADING_SUPPORT
11 #define _LIBCPP_THREADING_SUPPORT
18 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
19 #pragma GCC system_header
22 #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
23 # include <__external_threading>
24 #elif !defined(_LIBCPP_HAS_NO_THREADS)
26 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
30 # define _LIBCPP_NO_NATIVE_SEMAPHORES
32 # ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
33 # include <semaphore.h>
35 #elif defined(_LIBCPP_HAS_THREAD_API_C11)
39 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
40 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
41 defined(_LIBCPP_HAS_THREAD_API_WIN32)
42 #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
44 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
47 #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
48 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
50 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
53 typedef ::timespec __libcpp_timespec_t;
54 #endif // !defined(_LIBCPP_HAS_NO_THREADS)
57 #include <__undef_macros>
59 _LIBCPP_BEGIN_NAMESPACE_STD
61 #if !defined(_LIBCPP_HAS_NO_THREADS)
63 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
65 typedef pthread_mutex_t __libcpp_mutex_t;
66 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
68 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
71 typedef pthread_cond_t __libcpp_condvar_t;
72 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
74 #ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
76 typedef sem_t __libcpp_semaphore_t;
77 # define _LIBCPP_SEMAPHORE_MAX SEM_VALUE_MAX
81 typedef pthread_once_t __libcpp_exec_once_flag;
82 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
85 typedef pthread_t __libcpp_thread_id;
88 #define _LIBCPP_NULL_THREAD 0U
90 typedef pthread_t __libcpp_thread_t;
92 // Thread Local Storage
93 typedef pthread_key_t __libcpp_tls_key;
95 #define _LIBCPP_TLS_DESTRUCTOR_CC
96 #elif defined(_LIBCPP_HAS_THREAD_API_C11)
98 typedef mtx_t __libcpp_mutex_t;
99 // mtx_t is a struct so using {} for initialization is valid.
100 #define _LIBCPP_MUTEX_INITIALIZER {}
102 typedef mtx_t __libcpp_recursive_mutex_t;
104 // Condition Variable
105 typedef cnd_t __libcpp_condvar_t;
106 // cnd_t is a struct so using {} for initialization is valid.
107 #define _LIBCPP_CONDVAR_INITIALIZER {}
110 typedef once_flag __libcpp_exec_once_flag;
111 #define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
114 typedef thrd_t __libcpp_thread_id;
117 #define _LIBCPP_NULL_THREAD 0U
119 typedef thrd_t __libcpp_thread_t;
121 // Thread Local Storage
122 typedef tss_t __libcpp_tls_key;
124 #define _LIBCPP_TLS_DESTRUCTOR_CC
125 #elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
127 typedef void* __libcpp_mutex_t;
128 #define _LIBCPP_MUTEX_INITIALIZER 0
130 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
131 typedef void* __libcpp_recursive_mutex_t[6];
132 #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
133 typedef void* __libcpp_recursive_mutex_t[5];
135 # error Unsupported architecture
138 // Condition Variable
139 typedef void* __libcpp_condvar_t;
140 #define _LIBCPP_CONDVAR_INITIALIZER 0
143 typedef void* __libcpp_semaphore_t;
146 typedef void* __libcpp_exec_once_flag;
147 #define _LIBCPP_EXEC_ONCE_INITIALIZER 0
150 typedef long __libcpp_thread_id;
153 #define _LIBCPP_NULL_THREAD 0U
155 typedef void* __libcpp_thread_t;
157 // Thread Local Storage
158 typedef long __libcpp_tls_key;
160 #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
161 #endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
163 #if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
165 _LIBCPP_THREAD_ABI_VISIBILITY
166 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
168 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
169 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
171 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
172 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
174 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
175 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
177 _LIBCPP_THREAD_ABI_VISIBILITY
178 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
180 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
181 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
183 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
184 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
186 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
187 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
189 _LIBCPP_THREAD_ABI_VISIBILITY
190 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
192 // Condition variable
193 _LIBCPP_THREAD_ABI_VISIBILITY
194 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
196 _LIBCPP_THREAD_ABI_VISIBILITY
197 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
199 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
200 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
202 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
203 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
204 __libcpp_timespec_t *__ts);
206 _LIBCPP_THREAD_ABI_VISIBILITY
207 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
209 #ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
212 _LIBCPP_THREAD_ABI_VISIBILITY
213 bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init);
215 _LIBCPP_THREAD_ABI_VISIBILITY
216 bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem);
218 _LIBCPP_THREAD_ABI_VISIBILITY
219 bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem);
221 _LIBCPP_THREAD_ABI_VISIBILITY
222 bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem);
224 _LIBCPP_THREAD_ABI_VISIBILITY
225 bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns);
227 #endif // _LIBCPP_NO_NATIVE_SEMAPHORES
230 _LIBCPP_THREAD_ABI_VISIBILITY
231 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
232 void (*init_routine)());
235 _LIBCPP_THREAD_ABI_VISIBILITY
236 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
238 _LIBCPP_THREAD_ABI_VISIBILITY
239 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
242 _LIBCPP_THREAD_ABI_VISIBILITY
243 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
245 _LIBCPP_THREAD_ABI_VISIBILITY
246 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
249 _LIBCPP_THREAD_ABI_VISIBILITY
250 __libcpp_thread_id __libcpp_thread_get_current_id();
252 _LIBCPP_THREAD_ABI_VISIBILITY
253 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
255 _LIBCPP_THREAD_ABI_VISIBILITY
256 int __libcpp_thread_join(__libcpp_thread_t *__t);
258 _LIBCPP_THREAD_ABI_VISIBILITY
259 int __libcpp_thread_detach(__libcpp_thread_t *__t);
261 _LIBCPP_THREAD_ABI_VISIBILITY
262 void __libcpp_thread_yield();
264 _LIBCPP_THREAD_ABI_VISIBILITY
265 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
267 // Thread local storage
268 _LIBCPP_THREAD_ABI_VISIBILITY
269 int __libcpp_tls_create(__libcpp_tls_key* __key,
270 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
272 _LIBCPP_THREAD_ABI_VISIBILITY
273 void *__libcpp_tls_get(__libcpp_tls_key __key);
275 _LIBCPP_THREAD_ABI_VISIBILITY
276 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
278 #endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
280 struct __libcpp_timed_backoff_policy {
281 _LIBCPP_THREAD_ABI_VISIBILITY
282 bool operator()(chrono::nanoseconds __elapsed) const;
285 inline _LIBCPP_INLINE_VISIBILITY
286 bool __libcpp_timed_backoff_policy::operator()(chrono::nanoseconds __elapsed) const
288 if(__elapsed > chrono::milliseconds(128))
289 __libcpp_thread_sleep_for(chrono::milliseconds(8));
290 else if(__elapsed > chrono::microseconds(64))
291 __libcpp_thread_sleep_for(__elapsed / 2);
292 else if(__elapsed > chrono::microseconds(4))
293 __libcpp_thread_yield();
299 static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
301 template<class _Fn, class _BFn>
302 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
303 bool __libcpp_thread_poll_with_backoff(
304 _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero())
306 auto const __start = chrono::high_resolution_clock::now();
307 for(int __count = 0;;) {
309 return true; // _Fn completion means success
310 if(__count < __libcpp_polling_count) {
314 chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
315 if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
316 return false; // timeout failure
318 return false; // _BFn completion means failure
322 #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
323 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
326 namespace __thread_detail {
328 inline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
330 using namespace chrono;
331 seconds __s = duration_cast<seconds>(__ns);
332 __libcpp_timespec_t __ts;
333 typedef decltype(__ts.tv_sec) __ts_sec;
334 const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
336 if (__s.count() < __ts_sec_max)
338 __ts.tv_sec = static_cast<__ts_sec>(__s.count());
339 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
343 __ts.tv_sec = __ts_sec_max;
344 __ts.tv_nsec = 999999999; // (10^9 - 1)
352 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
354 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
356 pthread_mutexattr_t attr;
357 int __ec = pthread_mutexattr_init(&attr);
360 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
362 pthread_mutexattr_destroy(&attr);
365 __ec = pthread_mutex_init(__m, &attr);
367 pthread_mutexattr_destroy(&attr);
370 __ec = pthread_mutexattr_destroy(&attr);
372 pthread_mutex_destroy(__m);
378 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
380 return pthread_mutex_lock(__m);
383 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
385 return pthread_mutex_trylock(__m) == 0;
388 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
390 return pthread_mutex_unlock(__m);
393 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
395 return pthread_mutex_destroy(__m);
398 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
400 return pthread_mutex_lock(__m);
403 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
405 return pthread_mutex_trylock(__m) == 0;
408 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
410 return pthread_mutex_unlock(__m);
413 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
415 return pthread_mutex_destroy(__m);
418 // Condition Variable
419 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
421 return pthread_cond_signal(__cv);
424 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
426 return pthread_cond_broadcast(__cv);
429 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
431 return pthread_cond_wait(__cv, __m);
434 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
435 __libcpp_timespec_t *__ts)
437 return pthread_cond_timedwait(__cv, __m, __ts);
440 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
442 return pthread_cond_destroy(__cv);
445 #ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
448 bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init)
450 return sem_init(__sem, 0, __init) == 0;
453 bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem)
455 return sem_destroy(__sem) == 0;
458 bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem)
460 return sem_post(__sem) == 0;
463 bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem)
465 return sem_wait(__sem) == 0;
468 bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns)
470 auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns;
471 __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time);
472 return sem_timedwait(__sem, &__ts) == 0;
475 #endif //_LIBCPP_NO_NATIVE_SEMAPHORES
478 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
479 void (*init_routine)()) {
480 return pthread_once(flag, init_routine);
484 // Returns non-zero if the thread ids are equal, otherwise 0
485 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
487 return pthread_equal(t1, t2) != 0;
490 // Returns non-zero if t1 < t2, otherwise 0
491 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
497 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
501 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
504 return pthread_create(__t, 0, __func, __arg);
507 __libcpp_thread_id __libcpp_thread_get_current_id()
509 return pthread_self();
512 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
517 int __libcpp_thread_join(__libcpp_thread_t *__t)
519 return pthread_join(*__t, 0);
522 int __libcpp_thread_detach(__libcpp_thread_t *__t)
524 return pthread_detach(*__t);
527 void __libcpp_thread_yield()
532 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
534 __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
535 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
538 // Thread local storage
539 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
541 return pthread_key_create(__key, __at_exit);
544 void *__libcpp_tls_get(__libcpp_tls_key __key)
546 return pthread_getspecific(__key);
549 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
551 return pthread_setspecific(__key, __p);
554 #elif defined(_LIBCPP_HAS_THREAD_API_C11)
556 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
558 return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
561 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
563 return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
566 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
568 return mtx_trylock(__m) == thrd_success;
571 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
573 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
576 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
582 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
584 return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
587 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
589 return mtx_trylock(__m) == thrd_success;
592 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
594 return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
597 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
603 // Condition Variable
604 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
606 return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
609 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
611 return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
614 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
616 return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
619 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
622 int __ec = cnd_timedwait(__cv, __m, __ts);
623 return __ec == thrd_timedout ? ETIMEDOUT : __ec;
626 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
633 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
634 void (*init_routine)(void)) {
635 ::call_once(flag, init_routine);
640 // Returns non-zero if the thread ids are equal, otherwise 0
641 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
643 return thrd_equal(t1, t2) != 0;
646 // Returns non-zero if t1 < t2, otherwise 0
647 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
653 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
657 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
660 int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
661 return __ec == thrd_nomem ? ENOMEM : __ec;
664 __libcpp_thread_id __libcpp_thread_get_current_id()
666 return thrd_current();
669 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
674 int __libcpp_thread_join(__libcpp_thread_t *__t)
676 return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
679 int __libcpp_thread_detach(__libcpp_thread_t *__t)
681 return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
684 void __libcpp_thread_yield()
689 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
691 __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
692 thrd_sleep(&__ts, nullptr);
695 // Thread local storage
696 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
698 return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
701 void *__libcpp_tls_get(__libcpp_tls_key __key)
703 return tss_get(__key);
706 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
708 return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
714 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
716 class _LIBCPP_TYPE_VIS thread;
717 class _LIBCPP_TYPE_VIS __thread_id;
719 namespace this_thread
722 _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
726 template<> struct hash<__thread_id>;
728 class _LIBCPP_TEMPLATE_VIS __thread_id
730 // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
731 // NULL is the no-thread value on Darwin. Someone needs to check
732 // on other platforms. We assume 0 works everywhere for now.
733 __libcpp_thread_id __id_;
736 _LIBCPP_INLINE_VISIBILITY
737 __thread_id() _NOEXCEPT : __id_(0) {}
739 friend _LIBCPP_INLINE_VISIBILITY
740 bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
741 { // don't pass id==0 to underlying routines
742 if (__x.__id_ == 0) return __y.__id_ == 0;
743 if (__y.__id_ == 0) return false;
744 return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
746 friend _LIBCPP_INLINE_VISIBILITY
747 bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
748 {return !(__x == __y);}
749 friend _LIBCPP_INLINE_VISIBILITY
750 bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
751 { // id==0 is always less than any other thread_id
752 if (__x.__id_ == 0) return __y.__id_ != 0;
753 if (__y.__id_ == 0) return false;
754 return __libcpp_thread_id_less(__x.__id_, __y.__id_);
756 friend _LIBCPP_INLINE_VISIBILITY
757 bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
758 {return !(__y < __x);}
759 friend _LIBCPP_INLINE_VISIBILITY
760 bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
762 friend _LIBCPP_INLINE_VISIBILITY
763 bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
764 {return !(__x < __y);}
766 _LIBCPP_INLINE_VISIBILITY
767 void __reset() { __id_ = 0; }
769 template<class _CharT, class _Traits>
771 _LIBCPP_INLINE_VISIBILITY
772 basic_ostream<_CharT, _Traits>&
773 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
776 _LIBCPP_INLINE_VISIBILITY
777 __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
779 friend __thread_id this_thread::get_id() _NOEXCEPT;
780 friend class _LIBCPP_TYPE_VIS thread;
781 friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
784 namespace this_thread
787 inline _LIBCPP_INLINE_VISIBILITY
791 return __libcpp_thread_get_current_id();
796 #endif // !_LIBCPP_HAS_NO_THREADS
798 _LIBCPP_END_NAMESPACE_STD
802 #endif // _LIBCPP_THREADING_SUPPORT