Mercurial > hg > CbC > CbC_llvm
comparison libcxx/include/thread @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 2e18cbf3894f |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 // -*- C++ -*- | |
2 //===--------------------------- thread -----------------------------------===// | |
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_THREAD | |
11 #define _LIBCPP_THREAD | |
12 | |
13 /* | |
14 | |
15 thread synopsis | |
16 | |
17 namespace std | |
18 { | |
19 | |
20 class thread | |
21 { | |
22 public: | |
23 class id; | |
24 typedef pthread_t native_handle_type; | |
25 | |
26 thread() noexcept; | |
27 template <class F, class ...Args> explicit thread(F&& f, Args&&... args); | |
28 ~thread(); | |
29 | |
30 thread(const thread&) = delete; | |
31 thread(thread&& t) noexcept; | |
32 | |
33 thread& operator=(const thread&) = delete; | |
34 thread& operator=(thread&& t) noexcept; | |
35 | |
36 void swap(thread& t) noexcept; | |
37 | |
38 bool joinable() const noexcept; | |
39 void join(); | |
40 void detach(); | |
41 id get_id() const noexcept; | |
42 native_handle_type native_handle(); | |
43 | |
44 static unsigned hardware_concurrency() noexcept; | |
45 }; | |
46 | |
47 void swap(thread& x, thread& y) noexcept; | |
48 | |
49 class thread::id | |
50 { | |
51 public: | |
52 id() noexcept; | |
53 }; | |
54 | |
55 bool operator==(thread::id x, thread::id y) noexcept; | |
56 bool operator!=(thread::id x, thread::id y) noexcept; | |
57 bool operator< (thread::id x, thread::id y) noexcept; | |
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 | |
62 template<class charT, class traits> | |
63 basic_ostream<charT, traits>& | |
64 operator<<(basic_ostream<charT, traits>& out, thread::id id); | |
65 | |
66 namespace this_thread | |
67 { | |
68 | |
69 thread::id get_id() noexcept; | |
70 | |
71 void yield() noexcept; | |
72 | |
73 template <class Clock, class Duration> | |
74 void sleep_until(const chrono::time_point<Clock, Duration>& abs_time); | |
75 | |
76 template <class Rep, class Period> | |
77 void sleep_for(const chrono::duration<Rep, Period>& rel_time); | |
78 | |
79 } // this_thread | |
80 | |
81 } // std | |
82 | |
83 */ | |
84 | |
85 #include <__config> | |
86 #include <iosfwd> | |
87 #include <__functional_base> | |
88 #include <type_traits> | |
89 #include <cstddef> | |
90 #include <functional> | |
91 #include <memory> | |
92 #include <system_error> | |
93 #include <chrono> | |
94 #include <__mutex_base> | |
95 #ifndef _LIBCPP_CXX03_LANG | |
96 #include <tuple> | |
97 #endif | |
98 #include <__threading_support> | |
99 #include <__debug> | |
100 | |
101 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
102 #pragma GCC system_header | |
103 #endif | |
104 | |
105 _LIBCPP_PUSH_MACROS | |
106 #include <__undef_macros> | |
107 | |
108 #ifdef _LIBCPP_HAS_NO_THREADS | |
109 #error <thread> is not supported on this single threaded system | |
110 #else // !_LIBCPP_HAS_NO_THREADS | |
111 | |
112 _LIBCPP_BEGIN_NAMESPACE_STD | |
113 | |
114 template <class _Tp> class __thread_specific_ptr; | |
115 class _LIBCPP_TYPE_VIS __thread_struct; | |
116 class _LIBCPP_HIDDEN __thread_struct_imp; | |
117 class __assoc_sub_state; | |
118 | |
119 _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); | |
120 | |
121 class _LIBCPP_TYPE_VIS __thread_struct | |
122 { | |
123 __thread_struct_imp* __p_; | |
124 | |
125 __thread_struct(const __thread_struct&); | |
126 __thread_struct& operator=(const __thread_struct&); | |
127 public: | |
128 __thread_struct(); | |
129 ~__thread_struct(); | |
130 | |
131 void notify_all_at_thread_exit(condition_variable*, mutex*); | |
132 void __make_ready_at_thread_exit(__assoc_sub_state*); | |
133 }; | |
134 | |
135 template <class _Tp> | |
136 class __thread_specific_ptr | |
137 { | |
138 __libcpp_tls_key __key_; | |
139 | |
140 // Only __thread_local_data() may construct a __thread_specific_ptr | |
141 // and only with _Tp == __thread_struct. | |
142 static_assert((is_same<_Tp, __thread_struct>::value), ""); | |
143 __thread_specific_ptr(); | |
144 friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); | |
145 | |
146 __thread_specific_ptr(const __thread_specific_ptr&); | |
147 __thread_specific_ptr& operator=(const __thread_specific_ptr&); | |
148 | |
149 _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*); | |
150 | |
151 public: | |
152 typedef _Tp* pointer; | |
153 | |
154 ~__thread_specific_ptr(); | |
155 | |
156 _LIBCPP_INLINE_VISIBILITY | |
157 pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));} | |
158 _LIBCPP_INLINE_VISIBILITY | |
159 pointer operator*() const {return *get();} | |
160 _LIBCPP_INLINE_VISIBILITY | |
161 pointer operator->() const {return get();} | |
162 void set_pointer(pointer __p); | |
163 }; | |
164 | |
165 template <class _Tp> | |
166 void _LIBCPP_TLS_DESTRUCTOR_CC | |
167 __thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) | |
168 { | |
169 delete static_cast<pointer>(__p); | |
170 } | |
171 | |
172 template <class _Tp> | |
173 __thread_specific_ptr<_Tp>::__thread_specific_ptr() | |
174 { | |
175 int __ec = | |
176 __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit); | |
177 if (__ec) | |
178 __throw_system_error(__ec, "__thread_specific_ptr construction failed"); | |
179 } | |
180 | |
181 template <class _Tp> | |
182 __thread_specific_ptr<_Tp>::~__thread_specific_ptr() | |
183 { | |
184 // __thread_specific_ptr is only created with a static storage duration | |
185 // so this destructor is only invoked during program termination. Invoking | |
186 // pthread_key_delete(__key_) may prevent other threads from deleting their | |
187 // thread local data. For this reason we leak the key. | |
188 } | |
189 | |
190 template <class _Tp> | |
191 void | |
192 __thread_specific_ptr<_Tp>::set_pointer(pointer __p) | |
193 { | |
194 _LIBCPP_ASSERT(get() == nullptr, | |
195 "Attempting to overwrite thread local data"); | |
196 __libcpp_tls_set(__key_, __p); | |
197 } | |
198 | |
199 template<> | |
200 struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> | |
201 : public unary_function<__thread_id, size_t> | |
202 { | |
203 _LIBCPP_INLINE_VISIBILITY | |
204 size_t operator()(__thread_id __v) const _NOEXCEPT | |
205 { | |
206 return hash<__libcpp_thread_id>()(__v.__id_); | |
207 } | |
208 }; | |
209 | |
210 template<class _CharT, class _Traits> | |
211 _LIBCPP_INLINE_VISIBILITY | |
212 basic_ostream<_CharT, _Traits>& | |
213 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) | |
214 {return __os << __id.__id_;} | |
215 | |
216 class _LIBCPP_TYPE_VIS thread | |
217 { | |
218 __libcpp_thread_t __t_; | |
219 | |
220 thread(const thread&); | |
221 thread& operator=(const thread&); | |
222 public: | |
223 typedef __thread_id id; | |
224 typedef __libcpp_thread_t native_handle_type; | |
225 | |
226 _LIBCPP_INLINE_VISIBILITY | |
227 thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} | |
228 #ifndef _LIBCPP_CXX03_LANG | |
229 template <class _Fp, class ..._Args, | |
230 class = typename enable_if | |
231 < | |
232 !is_same<typename __uncvref<_Fp>::type, thread>::value | |
233 >::type | |
234 > | |
235 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS | |
236 explicit thread(_Fp&& __f, _Args&&... __args); | |
237 #else // _LIBCPP_CXX03_LANG | |
238 template <class _Fp> | |
239 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS | |
240 explicit thread(_Fp __f); | |
241 #endif | |
242 ~thread(); | |
243 | |
244 #ifndef _LIBCPP_CXX03_LANG | |
245 _LIBCPP_INLINE_VISIBILITY | |
246 thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = _LIBCPP_NULL_THREAD;} | |
247 _LIBCPP_INLINE_VISIBILITY | |
248 thread& operator=(thread&& __t) _NOEXCEPT; | |
249 #endif // _LIBCPP_CXX03_LANG | |
250 | |
251 _LIBCPP_INLINE_VISIBILITY | |
252 void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} | |
253 | |
254 _LIBCPP_INLINE_VISIBILITY | |
255 bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);} | |
256 void join(); | |
257 void detach(); | |
258 _LIBCPP_INLINE_VISIBILITY | |
259 id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);} | |
260 _LIBCPP_INLINE_VISIBILITY | |
261 native_handle_type native_handle() _NOEXCEPT {return __t_;} | |
262 | |
263 static unsigned hardware_concurrency() _NOEXCEPT; | |
264 }; | |
265 | |
266 #ifndef _LIBCPP_CXX03_LANG | |
267 | |
268 template <class _TSp, class _Fp, class ..._Args, size_t ..._Indices> | |
269 inline _LIBCPP_INLINE_VISIBILITY | |
270 void | |
271 __thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) | |
272 { | |
273 __invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); | |
274 } | |
275 | |
276 template <class _Fp> | |
277 _LIBCPP_INLINE_VISIBILITY | |
278 void* __thread_proxy(void* __vp) | |
279 { | |
280 // _Fp = std::tuple< unique_ptr<__thread_struct>, Functor, Args...> | |
281 std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); | |
282 __thread_local_data().set_pointer(_VSTD::get<0>(*__p).release()); | |
283 typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index; | |
284 __thread_execute(*__p, _Index()); | |
285 return nullptr; | |
286 } | |
287 | |
288 template <class _Fp, class ..._Args, | |
289 class | |
290 > | |
291 thread::thread(_Fp&& __f, _Args&&... __args) | |
292 { | |
293 typedef unique_ptr<__thread_struct> _TSPtr; | |
294 _TSPtr __tsp(new __thread_struct); | |
295 typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; | |
296 _VSTD::unique_ptr<_Gp> __p( | |
297 new _Gp(std::move(__tsp), | |
298 __decay_copy(_VSTD::forward<_Fp>(__f)), | |
299 __decay_copy(_VSTD::forward<_Args>(__args))...)); | |
300 int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); | |
301 if (__ec == 0) | |
302 __p.release(); | |
303 else | |
304 __throw_system_error(__ec, "thread constructor failed"); | |
305 } | |
306 | |
307 inline | |
308 thread& | |
309 thread::operator=(thread&& __t) _NOEXCEPT | |
310 { | |
311 if (!__libcpp_thread_isnull(&__t_)) | |
312 terminate(); | |
313 __t_ = __t.__t_; | |
314 __t.__t_ = _LIBCPP_NULL_THREAD; | |
315 return *this; | |
316 } | |
317 | |
318 #else // _LIBCPP_CXX03_LANG | |
319 | |
320 template <class _Fp> | |
321 struct __thread_invoke_pair { | |
322 // This type is used to pass memory for thread local storage and a functor | |
323 // to a newly created thread because std::pair doesn't work with | |
324 // std::unique_ptr in C++03. | |
325 __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} | |
326 unique_ptr<__thread_struct> __tsp_; | |
327 _Fp __fn_; | |
328 }; | |
329 | |
330 template <class _Fp> | |
331 void* __thread_proxy_cxx03(void* __vp) | |
332 { | |
333 std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); | |
334 __thread_local_data().set_pointer(__p->__tsp_.release()); | |
335 (__p->__fn_)(); | |
336 return nullptr; | |
337 } | |
338 | |
339 template <class _Fp> | |
340 thread::thread(_Fp __f) | |
341 { | |
342 | |
343 typedef __thread_invoke_pair<_Fp> _InvokePair; | |
344 typedef std::unique_ptr<_InvokePair> _PairPtr; | |
345 _PairPtr __pp(new _InvokePair(__f)); | |
346 int __ec = __libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); | |
347 if (__ec == 0) | |
348 __pp.release(); | |
349 else | |
350 __throw_system_error(__ec, "thread constructor failed"); | |
351 } | |
352 | |
353 #endif // _LIBCPP_CXX03_LANG | |
354 | |
355 inline _LIBCPP_INLINE_VISIBILITY | |
356 void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} | |
357 | |
358 namespace this_thread | |
359 { | |
360 | |
361 _LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns); | |
362 | |
363 template <class _Rep, class _Period> | |
364 void | |
365 sleep_for(const chrono::duration<_Rep, _Period>& __d) | |
366 { | |
367 using namespace chrono; | |
368 if (__d > duration<_Rep, _Period>::zero()) | |
369 { | |
370 #if defined(_LIBCPP_COMPILER_GCC) && (__powerpc__ || __POWERPC__) | |
371 // GCC's long double const folding is incomplete for IBM128 long doubles. | |
372 _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max(); | |
373 #else | |
374 _LIBCPP_CONSTEXPR duration<long double> _Max = duration<long double>(ULLONG_MAX/1000000000ULL) ; | |
375 #endif | |
376 nanoseconds __ns; | |
377 if (__d < _Max) | |
378 { | |
379 __ns = duration_cast<nanoseconds>(__d); | |
380 if (__ns < __d) | |
381 ++__ns; | |
382 } | |
383 else | |
384 __ns = nanoseconds::max(); | |
385 sleep_for(__ns); | |
386 } | |
387 } | |
388 | |
389 template <class _Clock, class _Duration> | |
390 void | |
391 sleep_until(const chrono::time_point<_Clock, _Duration>& __t) | |
392 { | |
393 using namespace chrono; | |
394 mutex __mut; | |
395 condition_variable __cv; | |
396 unique_lock<mutex> __lk(__mut); | |
397 while (_Clock::now() < __t) | |
398 __cv.wait_until(__lk, __t); | |
399 } | |
400 | |
401 template <class _Duration> | |
402 inline _LIBCPP_INLINE_VISIBILITY | |
403 void | |
404 sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) | |
405 { | |
406 using namespace chrono; | |
407 sleep_for(__t - steady_clock::now()); | |
408 } | |
409 | |
410 inline _LIBCPP_INLINE_VISIBILITY | |
411 void yield() _NOEXCEPT {__libcpp_thread_yield();} | |
412 | |
413 } // this_thread | |
414 | |
415 _LIBCPP_END_NAMESPACE_STD | |
416 | |
417 #endif // !_LIBCPP_HAS_NO_THREADS | |
418 | |
419 _LIBCPP_POP_MACROS | |
420 | |
421 #endif // _LIBCPP_THREAD |