]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/libcxx/include/__threading_support
Fix BUILD_WITH_STRICT_TMPPATH builds
[FreeBSD/FreeBSD.git] / contrib / llvm-project / libcxx / include / __threading_support
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
47 typedef ::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
59 typedef pthread_mutex_t __libcpp_mutex_t;
60 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
61
62 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
63
64 // Condition Variable
65 typedef pthread_cond_t __libcpp_condvar_t;
66 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
67
68 // Execute once
69 typedef pthread_once_t __libcpp_exec_once_flag;
70 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
71
72 // Thread id
73 typedef pthread_t __libcpp_thread_id;
74
75 // Thread
76 #define _LIBCPP_NULL_THREAD 0U
77
78 typedef pthread_t __libcpp_thread_t;
79
80 // Thread Local Storage
81 typedef pthread_key_t __libcpp_tls_key;
82
83 #define _LIBCPP_TLS_DESTRUCTOR_CC
84 #elif defined(_LIBCPP_HAS_THREAD_API_C11)
85 // Mutex
86 typedef mtx_t __libcpp_mutex_t;
87 // mtx_t is a struct so using {} for initialization is valid.
88 #define _LIBCPP_MUTEX_INITIALIZER {}
89
90 typedef mtx_t __libcpp_recursive_mutex_t;
91
92 // Condition Variable
93 typedef 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
98 typedef once_flag __libcpp_exec_once_flag;
99 #define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
100
101 // Thread id
102 typedef thrd_t __libcpp_thread_id;
103
104 // Thread
105 #define _LIBCPP_NULL_THREAD 0U
106
107 typedef thrd_t __libcpp_thread_t;
108
109 // Thread Local Storage
110 typedef tss_t __libcpp_tls_key;
111
112 #define _LIBCPP_TLS_DESTRUCTOR_CC
113 #elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
114 // Mutex
115 typedef void* __libcpp_mutex_t;
116 #define _LIBCPP_MUTEX_INITIALIZER 0
117
118 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
119 typedef void* __libcpp_recursive_mutex_t[6];
120 #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
121 typedef void* __libcpp_recursive_mutex_t[5];
122 #else
123 # error Unsupported architecture
124 #endif
125
126 // Condition Variable
127 typedef void* __libcpp_condvar_t;
128 #define _LIBCPP_CONDVAR_INITIALIZER 0
129
130 // Execute Once
131 typedef void* __libcpp_exec_once_flag;
132 #define _LIBCPP_EXEC_ONCE_INITIALIZER 0
133
134 // Thread ID
135 typedef long __libcpp_thread_id;
136
137 // Thread
138 #define _LIBCPP_NULL_THREAD 0U
139
140 typedef void* __libcpp_thread_t;
141
142 // Thread Local Storage
143 typedef 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
151 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
152
153 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
154 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
155
156 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
157 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
158
159 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
160 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
161
162 _LIBCPP_THREAD_ABI_VISIBILITY
163 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
164
165 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
166 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
167
168 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
169 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
170
171 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
172 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
173
174 _LIBCPP_THREAD_ABI_VISIBILITY
175 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
176
177 // Condition variable
178 _LIBCPP_THREAD_ABI_VISIBILITY
179 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
180
181 _LIBCPP_THREAD_ABI_VISIBILITY
182 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
183
184 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
185 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
186
187 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
188 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
189                                __libcpp_timespec_t *__ts);
190
191 _LIBCPP_THREAD_ABI_VISIBILITY
192 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
193
194 // Execute once
195 _LIBCPP_THREAD_ABI_VISIBILITY
196 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
197                           void (*init_routine)());
198
199 // Thread id
200 _LIBCPP_THREAD_ABI_VISIBILITY
201 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
202
203 _LIBCPP_THREAD_ABI_VISIBILITY
204 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
205
206 // Thread
207 _LIBCPP_THREAD_ABI_VISIBILITY
208 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
209
210 _LIBCPP_THREAD_ABI_VISIBILITY
211 int __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
221 int __libcpp_thread_join(__libcpp_thread_t *__t);
222
223 _LIBCPP_THREAD_ABI_VISIBILITY
224 int __libcpp_thread_detach(__libcpp_thread_t *__t);
225
226 _LIBCPP_THREAD_ABI_VISIBILITY
227 void __libcpp_thread_yield();
228
229 _LIBCPP_THREAD_ABI_VISIBILITY
230 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
231
232 // Thread local storage
233 _LIBCPP_THREAD_ABI_VISIBILITY
234 int __libcpp_tls_create(__libcpp_tls_key* __key,
235                         void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
236
237 _LIBCPP_THREAD_ABI_VISIBILITY
238 void *__libcpp_tls_get(__libcpp_tls_key __key);
239
240 _LIBCPP_THREAD_ABI_VISIBILITY
241 int __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
248 namespace __thread_detail {
249
250 inline __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
276 int __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
300 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
301 {
302   return pthread_mutex_lock(__m);
303 }
304
305 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
306 {
307   return pthread_mutex_trylock(__m) == 0;
308 }
309
310 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
311 {
312   return pthread_mutex_unlock(__m);
313 }
314
315 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
316 {
317   return pthread_mutex_destroy(__m);
318 }
319
320 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
321 {
322   return pthread_mutex_lock(__m);
323 }
324
325 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
326 {
327   return pthread_mutex_trylock(__m) == 0;
328 }
329
330 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
331 {
332   return pthread_mutex_unlock(__m);
333 }
334
335 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
336 {
337   return pthread_mutex_destroy(__m);
338 }
339
340 // Condition Variable
341 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
342 {
343   return pthread_cond_signal(__cv);
344 }
345
346 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
347 {
348   return pthread_cond_broadcast(__cv);
349 }
350
351 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
352 {
353   return pthread_cond_wait(__cv, __m);
354 }
355
356 int __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
362 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
363 {
364   return pthread_cond_destroy(__cv);
365 }
366
367 // Execute once
368 int __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
375 bool __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
381 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
382 {
383   return t1 < t2;
384 }
385
386 // Thread
387 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
388   return *__t == 0;
389 }
390
391 int __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
407 int __libcpp_thread_join(__libcpp_thread_t *__t)
408 {
409   return pthread_join(*__t, 0);
410 }
411
412 int __libcpp_thread_detach(__libcpp_thread_t *__t)
413 {
414   return pthread_detach(*__t);
415 }
416
417 void __libcpp_thread_yield()
418 {
419   sched_yield();
420 }
421
422 void __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
429 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
430 {
431   return pthread_key_create(__key, __at_exit);
432 }
433
434 void *__libcpp_tls_get(__libcpp_tls_key __key)
435 {
436   return pthread_getspecific(__key);
437 }
438
439 int __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
446 int __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
451 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
452 {
453   return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
454 }
455
456 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
457 {
458   return mtx_trylock(__m) == thrd_success;
459 }
460
461 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
462 {
463   return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
464 }
465
466 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
467 {
468   mtx_destroy(__m);
469   return 0;
470 }
471
472 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
473 {
474   return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
475 }
476
477 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
478 {
479   return mtx_trylock(__m) == thrd_success;
480 }
481
482 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
483 {
484   return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
485 }
486
487 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
488 {
489   mtx_destroy(__m);
490   return 0;
491 }
492
493 // Condition Variable
494 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
495 {
496   return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
497 }
498
499 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
500 {
501   return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
502 }
503
504 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
505 {
506   return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
507 }
508
509 int __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
516 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
517 {
518   cnd_destroy(__cv);
519   return 0;
520 }
521
522 // Execute once
523 int __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
531 bool __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
537 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
538 {
539   return t1 < t2;
540 }
541
542 // Thread
543 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
544   return *__t == 0;
545 }
546
547 int __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
564 int __libcpp_thread_join(__libcpp_thread_t *__t)
565 {
566   return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
567 }
568
569 int __libcpp_thread_detach(__libcpp_thread_t *__t)
570 {
571   return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
572 }
573
574 void __libcpp_thread_yield()
575 {
576   thrd_yield();
577 }
578
579 void __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
586 int __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
591 void *__libcpp_tls_get(__libcpp_tls_key __key)
592 {
593   return tss_get(__key);
594 }
595
596 int __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
605 class _LIBCPP_TYPE_VIS thread;
606 class _LIBCPP_TYPE_VIS __thread_id;
607
608 namespace this_thread
609 {
610
611 _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
612
613 }  // this_thread
614
615 template<> struct hash<__thread_id>;
616
617 class _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
624 public:
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
664 private:
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
673 namespace this_thread
674 {
675
676 inline _LIBCPP_INLINE_VISIBILITY
677 __thread_id
678 get_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