]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/libc++/include/thread
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / libc++ / include / thread
1 // -*- C++ -*-
2 //===--------------------------- thread -----------------------------------===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #ifndef _LIBCPP_THREAD
12 #define _LIBCPP_THREAD
13
14 /*
15
16     thread synopsis
17
18 #define __STDCPP_THREADS__ __cplusplus
19
20 namespace std
21 {
22
23 class thread
24 {
25 public:
26     class id;
27     typedef pthread_t native_handle_type;
28
29     thread() noexcept;
30     template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
31     ~thread();
32
33     thread(const thread&) = delete;
34     thread(thread&& t) noexcept;
35
36     thread& operator=(const thread&) = delete;
37     thread& operator=(thread&& t) noexcept;
38
39     void swap(thread& t) noexcept;
40
41     bool joinable() const noexcept;
42     void join();
43     void detach();
44     id get_id() const noexcept;
45     native_handle_type native_handle();
46
47     static unsigned hardware_concurrency() noexcept;
48 };
49
50 void swap(thread& x, thread& y) noexcept;
51
52 class thread::id
53 {
54 public:
55     id() noexcept;
56 };
57
58 bool operator==(thread::id x, thread::id y) noexcept;
59 bool operator!=(thread::id x, thread::id y) noexcept;
60 bool operator< (thread::id x, thread::id y) noexcept;
61 bool operator<=(thread::id x, thread::id y) noexcept;
62 bool operator> (thread::id x, thread::id y) noexcept;
63 bool operator>=(thread::id x, thread::id y) noexcept;
64
65 template<class charT, class traits>
66 basic_ostream<charT, traits>&
67 operator<<(basic_ostream<charT, traits>& out, thread::id id);
68
69 namespace this_thread
70 {
71
72 thread::id get_id() noexcept;
73
74 void yield() noexcept;
75
76 template <class Clock, class Duration>
77 void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
78
79 template <class Rep, class Period>
80 void sleep_for(const chrono::duration<Rep, Period>& rel_time);
81
82 }  // this_thread
83
84 }  // std
85
86 */
87
88 #include <__config>
89 #include <iosfwd>
90 #include <__functional_base>
91 #include <type_traits>
92 #include <cstddef>
93 #include <functional>
94 #include <memory>
95 #include <system_error>
96 #include <chrono>
97 #include <__mutex_base>
98 #ifndef _LIBCPP_HAS_NO_VARIADICS
99 #include <tuple>
100 #endif
101 #include <pthread.h>
102 #include <sched.h>
103
104 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
105 #pragma GCC system_header
106 #endif
107
108 #define __STDCPP_THREADS__ __cplusplus
109
110 #ifdef _LIBCPP_HAS_NO_THREADS
111 #error <thread> is not supported on this single threaded system
112 #else // !_LIBCPP_HAS_NO_THREADS
113
114 _LIBCPP_BEGIN_NAMESPACE_STD
115
116 template <class _Tp>
117 class __thread_specific_ptr
118 {
119     pthread_key_t __key_;
120
121     __thread_specific_ptr(const __thread_specific_ptr&);
122     __thread_specific_ptr& operator=(const __thread_specific_ptr&);
123
124     static void __at_thread_exit(void*);
125 public:
126     typedef _Tp* pointer;
127
128     __thread_specific_ptr();
129     ~__thread_specific_ptr();
130
131     _LIBCPP_INLINE_VISIBILITY
132     pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));}
133     _LIBCPP_INLINE_VISIBILITY
134     pointer operator*() const {return *get();}
135     _LIBCPP_INLINE_VISIBILITY
136     pointer operator->() const {return get();}
137     pointer release();
138     void reset(pointer __p = nullptr);
139 };
140
141 template <class _Tp>
142 void
143 __thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)
144 {
145     delete static_cast<pointer>(__p);
146 }
147
148 template <class _Tp>
149 __thread_specific_ptr<_Tp>::__thread_specific_ptr()
150 {
151     int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
152 #ifndef _LIBCPP_NO_EXCEPTIONS
153     if (__ec)
154         throw system_error(error_code(__ec, system_category()),
155                            "__thread_specific_ptr construction failed");
156 #endif
157 }
158
159 template <class _Tp>
160 __thread_specific_ptr<_Tp>::~__thread_specific_ptr()
161 {
162     pthread_key_delete(__key_);
163 }
164
165 template <class _Tp>
166 typename __thread_specific_ptr<_Tp>::pointer
167 __thread_specific_ptr<_Tp>::release()
168 {
169     pointer __p = get();
170     pthread_setspecific(__key_, 0);
171     return __p;
172 }
173
174 template <class _Tp>
175 void
176 __thread_specific_ptr<_Tp>::reset(pointer __p)
177 {
178     pointer __p_old = get();
179     pthread_setspecific(__key_, __p);
180     delete __p_old;
181 }
182
183 class _LIBCPP_TYPE_VIS thread;
184 class _LIBCPP_TYPE_VIS __thread_id;
185
186 namespace this_thread
187 {
188
189 _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
190
191 }  // this_thread
192
193 template<> struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>;
194
195 class _LIBCPP_TYPE_VIS_ONLY __thread_id
196 {
197     // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
198     // NULL is the no-thread value on Darwin.  Someone needs to check
199     // on other platforms.  We assume 0 works everywhere for now.
200     pthread_t __id_;
201
202 public:
203     _LIBCPP_INLINE_VISIBILITY
204     __thread_id() _NOEXCEPT : __id_(0) {}
205
206     friend _LIBCPP_INLINE_VISIBILITY
207         bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
208         {return __x.__id_ == __y.__id_;}
209     friend _LIBCPP_INLINE_VISIBILITY
210         bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
211         {return !(__x == __y);}
212     friend _LIBCPP_INLINE_VISIBILITY
213         bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
214         {return __x.__id_ < __y.__id_;}
215     friend _LIBCPP_INLINE_VISIBILITY
216         bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
217         {return !(__y < __x);}
218     friend _LIBCPP_INLINE_VISIBILITY
219         bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
220         {return   __y < __x ;}
221     friend _LIBCPP_INLINE_VISIBILITY
222         bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
223         {return !(__x < __y);}
224
225     template<class _CharT, class _Traits>
226     friend
227     _LIBCPP_INLINE_VISIBILITY
228     basic_ostream<_CharT, _Traits>&
229     operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
230         {return __os << __id.__id_;}
231
232 private:
233     _LIBCPP_INLINE_VISIBILITY
234     __thread_id(pthread_t __id) : __id_(__id) {}
235
236     friend __thread_id this_thread::get_id() _NOEXCEPT;
237     friend class _LIBCPP_TYPE_VIS thread;
238     friend struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>;
239 };
240
241 template<>
242 struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>
243     : public unary_function<__thread_id, size_t>
244 {
245     _LIBCPP_INLINE_VISIBILITY
246     size_t operator()(__thread_id __v) const
247     {
248         return hash<pthread_t>()(__v.__id_);
249     }
250 };
251
252 namespace this_thread
253 {
254
255 inline _LIBCPP_INLINE_VISIBILITY
256 __thread_id
257 get_id() _NOEXCEPT
258 {
259     return pthread_self();
260 }
261
262 }  // this_thread
263
264 class _LIBCPP_TYPE_VIS thread
265 {
266     pthread_t __t_;
267
268     thread(const thread&);
269     thread& operator=(const thread&);
270 public:
271     typedef __thread_id id;
272     typedef pthread_t native_handle_type;
273
274     _LIBCPP_INLINE_VISIBILITY
275     thread() _NOEXCEPT : __t_(0) {}
276 #ifndef _LIBCPP_HAS_NO_VARIADICS
277     template <class _Fp, class ..._Args,
278               class = typename enable_if
279               <
280                    !is_same<typename decay<_Fp>::type, thread>::value
281               >::type
282              >
283         explicit thread(_Fp&& __f, _Args&&... __args);
284 #else  // _LIBCPP_HAS_NO_VARIADICS
285     template <class _Fp> explicit thread(_Fp __f);
286 #endif
287     ~thread();
288
289 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
290     _LIBCPP_INLINE_VISIBILITY
291     thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;}
292     thread& operator=(thread&& __t) _NOEXCEPT;
293 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
294
295     _LIBCPP_INLINE_VISIBILITY
296     void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);}
297
298     _LIBCPP_INLINE_VISIBILITY
299     bool joinable() const _NOEXCEPT {return __t_ != 0;}
300     void join();
301     void detach();
302     _LIBCPP_INLINE_VISIBILITY
303     id get_id() const _NOEXCEPT {return __t_;}
304     _LIBCPP_INLINE_VISIBILITY
305     native_handle_type native_handle() _NOEXCEPT {return __t_;}
306
307     static unsigned hardware_concurrency() _NOEXCEPT;
308 };
309
310 class __assoc_sub_state;
311
312 class _LIBCPP_HIDDEN __thread_struct_imp;
313
314 class _LIBCPP_TYPE_VIS __thread_struct
315 {
316     __thread_struct_imp* __p_;
317
318     __thread_struct(const __thread_struct&);
319     __thread_struct& operator=(const __thread_struct&);
320 public:
321     __thread_struct();
322     ~__thread_struct();
323
324     void notify_all_at_thread_exit(condition_variable*, mutex*);
325     void __make_ready_at_thread_exit(__assoc_sub_state*);
326 };
327
328 _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
329
330 #ifndef _LIBCPP_HAS_NO_VARIADICS
331
332 template <class _Fp, class ..._Args, size_t ..._Indices>
333 inline _LIBCPP_INLINE_VISIBILITY
334 void
335 __thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>)
336 {
337     __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
338 }
339
340 template <class _Fp>
341 void*
342 __thread_proxy(void* __vp)
343 {
344     __thread_local_data().reset(new __thread_struct);
345     std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
346     typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
347     __thread_execute(*__p, _Index());
348     return nullptr;
349 }
350
351 template <class _Fp, class ..._Args,
352           class
353          >
354 thread::thread(_Fp&& __f, _Args&&... __args)
355 {
356     typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
357     _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)),
358                                 __decay_copy(_VSTD::forward<_Args>(__args))...));
359     int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get());
360     if (__ec == 0)
361         __p.release();
362     else
363         __throw_system_error(__ec, "thread constructor failed");
364 }
365
366 #else  // _LIBCPP_HAS_NO_VARIADICS
367
368 template <class _Fp>
369 void*
370 __thread_proxy(void* __vp)
371 {
372     __thread_local_data().reset(new __thread_struct);
373     std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
374     (*__p)();
375     return nullptr;
376 }
377
378 template <class _Fp>
379 thread::thread(_Fp __f)
380 {
381     std::unique_ptr<_Fp> __p(new _Fp(__f));
382     int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get());
383     if (__ec == 0)
384         __p.release();
385     else
386         __throw_system_error(__ec, "thread constructor failed");
387 }
388
389 #endif  // _LIBCPP_HAS_NO_VARIADICS
390
391 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
392
393 inline _LIBCPP_INLINE_VISIBILITY
394 thread&
395 thread::operator=(thread&& __t) _NOEXCEPT
396 {
397     if (__t_ != 0)
398         terminate();
399     __t_ = __t.__t_;
400     __t.__t_ = 0;
401     return *this;
402 }
403
404 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
405
406 inline _LIBCPP_INLINE_VISIBILITY
407 void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);}
408
409 namespace this_thread
410 {
411
412 _LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& ns);
413
414 template <class _Rep, class _Period>
415 void
416 sleep_for(const chrono::duration<_Rep, _Period>& __d)
417 {
418     using namespace chrono;
419     if (__d > duration<_Rep, _Period>::zero())
420     {
421         _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max();
422         nanoseconds __ns;
423         if (__d < _Max)
424         {
425             __ns = duration_cast<nanoseconds>(__d);
426             if (__ns < __d)
427                 ++__ns;
428         }
429         else
430             __ns = nanoseconds::max();
431         sleep_for(__ns);
432     }
433 }
434
435 template <class _Clock, class _Duration>
436 void
437 sleep_until(const chrono::time_point<_Clock, _Duration>& __t)
438 {
439     using namespace chrono;
440     mutex __mut;
441     condition_variable __cv;
442     unique_lock<mutex> __lk(__mut);
443     while (_Clock::now() < __t)
444         __cv.wait_until(__lk, __t);
445 }
446
447 template <class _Duration>
448 inline _LIBCPP_INLINE_VISIBILITY
449 void
450 sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
451 {
452     using namespace chrono;
453     sleep_for(__t - steady_clock::now());
454 }
455
456 inline _LIBCPP_INLINE_VISIBILITY
457 void yield() _NOEXCEPT {sched_yield();}
458
459 }  // this_thread
460
461 _LIBCPP_END_NAMESPACE_STD
462
463 #endif // !_LIBCPP_HAS_NO_THREADS
464
465 #endif  // _LIBCPP_THREAD