Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/thread/detail/thread.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 #ifndef BOOST_THREAD_THREAD_COMMON_HPP | |
2 #define BOOST_THREAD_THREAD_COMMON_HPP | |
3 // Distributed under the Boost Software License, Version 1.0. (See | |
4 // accompanying file LICENSE_1_0.txt or copy at | |
5 // http://www.boost.org/LICENSE_1_0.txt) | |
6 // (C) Copyright 2007-2010 Anthony Williams | |
7 // (C) Copyright 20011-2012 Vicente J. Botet Escriba | |
8 | |
9 #include <boost/thread/detail/config.hpp> | |
10 | |
11 #include <boost/thread/exceptions.hpp> | |
12 #ifndef BOOST_NO_IOSTREAM | |
13 #include <ostream> | |
14 #endif | |
15 #include <boost/thread/detail/move.hpp> | |
16 #include <boost/thread/mutex.hpp> | |
17 #if defined BOOST_THREAD_USES_DATETIME | |
18 #include <boost/thread/xtime.hpp> | |
19 #endif | |
20 #include <boost/thread/detail/thread_heap_alloc.hpp> | |
21 #include <boost/thread/detail/make_tuple_indices.hpp> | |
22 #include <boost/thread/detail/invoke.hpp> | |
23 #include <boost/thread/detail/is_convertible.hpp> | |
24 #include <boost/assert.hpp> | |
25 #include <list> | |
26 #include <algorithm> | |
27 #include <boost/ref.hpp> | |
28 #include <boost/cstdint.hpp> | |
29 #include <boost/bind.hpp> | |
30 #include <stdlib.h> | |
31 #include <memory> | |
32 #include <boost/utility/enable_if.hpp> | |
33 #include <boost/type_traits/remove_reference.hpp> | |
34 #include <boost/io/ios_state.hpp> | |
35 #include <boost/type_traits/is_same.hpp> | |
36 #include <boost/type_traits/decay.hpp> | |
37 #include <boost/functional/hash.hpp> | |
38 #ifdef BOOST_THREAD_USES_CHRONO | |
39 #include <boost/chrono/system_clocks.hpp> | |
40 #include <boost/chrono/ceil.hpp> | |
41 #endif | |
42 | |
43 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
44 #include <tuple> | |
45 #endif | |
46 #include <boost/config/abi_prefix.hpp> | |
47 | |
48 #ifdef BOOST_MSVC | |
49 #pragma warning(push) | |
50 #pragma warning(disable:4251) | |
51 #endif | |
52 | |
53 namespace boost | |
54 { | |
55 | |
56 namespace detail | |
57 { | |
58 | |
59 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
60 | |
61 template<typename F, class ...ArgTypes> | |
62 class thread_data: | |
63 public detail::thread_data_base | |
64 { | |
65 public: | |
66 BOOST_THREAD_NO_COPYABLE(thread_data) | |
67 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
68 thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_): | |
69 fp(boost::forward<F>(f_), boost::forward<ArgTypes>(args_)...) | |
70 {} | |
71 #endif | |
72 template <std::size_t ...Indices> | |
73 void run2(tuple_indices<Indices...>) | |
74 { | |
75 | |
76 invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...); | |
77 } | |
78 void run() | |
79 { | |
80 typedef typename make_tuple_indices<std::tuple_size<std::tuple<F, ArgTypes...> >::value, 1>::type index_type; | |
81 | |
82 run2(index_type()); | |
83 } | |
84 | |
85 private: | |
86 std::tuple<typename decay<F>::type, typename decay<ArgTypes>::type...> fp; | |
87 }; | |
88 #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
89 | |
90 template<typename F> | |
91 class thread_data: | |
92 public detail::thread_data_base | |
93 { | |
94 public: | |
95 BOOST_THREAD_NO_COPYABLE(thread_data) | |
96 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
97 thread_data(BOOST_THREAD_RV_REF(F) f_): | |
98 f(boost::forward<F>(f_)) | |
99 {} | |
100 // This overloading must be removed if we want the packaged_task's tests to pass. | |
101 // thread_data(F& f_): | |
102 // f(f_) | |
103 // {} | |
104 #else | |
105 | |
106 thread_data(BOOST_THREAD_RV_REF(F) f_): | |
107 f(f_) | |
108 {} | |
109 thread_data(F f_): | |
110 f(f_) | |
111 {} | |
112 #endif | |
113 //thread_data() {} | |
114 | |
115 void run() | |
116 { | |
117 f(); | |
118 } | |
119 | |
120 private: | |
121 F f; | |
122 }; | |
123 | |
124 template<typename F> | |
125 class thread_data<boost::reference_wrapper<F> >: | |
126 public detail::thread_data_base | |
127 { | |
128 private: | |
129 F& f; | |
130 public: | |
131 BOOST_THREAD_NO_COPYABLE(thread_data) | |
132 thread_data(boost::reference_wrapper<F> f_): | |
133 f(f_) | |
134 {} | |
135 void run() | |
136 { | |
137 f(); | |
138 } | |
139 }; | |
140 | |
141 template<typename F> | |
142 class thread_data<const boost::reference_wrapper<F> >: | |
143 public detail::thread_data_base | |
144 { | |
145 private: | |
146 F& f; | |
147 public: | |
148 BOOST_THREAD_NO_COPYABLE(thread_data) | |
149 thread_data(const boost::reference_wrapper<F> f_): | |
150 f(f_) | |
151 {} | |
152 void run() | |
153 { | |
154 f(); | |
155 } | |
156 }; | |
157 #endif | |
158 } | |
159 | |
160 class BOOST_THREAD_DECL thread | |
161 { | |
162 public: | |
163 typedef thread_attributes attributes; | |
164 | |
165 BOOST_THREAD_MOVABLE_ONLY(thread) | |
166 private: | |
167 | |
168 struct dummy; | |
169 | |
170 void release_handle(); | |
171 | |
172 detail::thread_data_ptr thread_info; | |
173 | |
174 private: | |
175 bool start_thread_noexcept(); | |
176 bool start_thread_noexcept(const attributes& attr); | |
177 public: | |
178 void start_thread() | |
179 { | |
180 if (!start_thread_noexcept()) | |
181 { | |
182 boost::throw_exception(thread_resource_error()); | |
183 } | |
184 } | |
185 void start_thread(const attributes& attr) | |
186 { | |
187 if (!start_thread_noexcept(attr)) | |
188 { | |
189 boost::throw_exception(thread_resource_error()); | |
190 } | |
191 } | |
192 | |
193 explicit thread(detail::thread_data_ptr data); | |
194 | |
195 detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const; | |
196 | |
197 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
198 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
199 template<typename F, class ...ArgTypes> | |
200 static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_RV_REF(ArgTypes)... args) | |
201 { | |
202 return detail::thread_data_ptr(detail::heap_new< | |
203 detail::thread_data<typename boost::remove_reference<F>::type, ArgTypes...> | |
204 >( | |
205 boost::forward<F>(f), boost::forward<ArgTypes>(args)... | |
206 ) | |
207 ); | |
208 } | |
209 #else | |
210 template<typename F> | |
211 static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f) | |
212 { | |
213 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >( | |
214 boost::forward<F>(f))); | |
215 } | |
216 #endif | |
217 static inline detail::thread_data_ptr make_thread_info(void (*f)()) | |
218 { | |
219 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >( | |
220 boost::forward<void(*)()>(f))); | |
221 } | |
222 #else | |
223 template<typename F> | |
224 static inline detail::thread_data_ptr make_thread_info(F f | |
225 , typename disable_if_c< | |
226 //boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value || | |
227 is_same<typename decay<F>::type, thread>::value, | |
228 dummy* >::type=0 | |
229 ) | |
230 { | |
231 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f)); | |
232 } | |
233 template<typename F> | |
234 static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f) | |
235 { | |
236 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f)); | |
237 } | |
238 | |
239 #endif | |
240 public: | |
241 #if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. | |
242 #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) | |
243 thread(const volatile thread&); | |
244 #endif | |
245 #endif | |
246 thread() BOOST_NOEXCEPT; | |
247 ~thread() | |
248 { | |
249 | |
250 #if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE | |
251 if (joinable()) { | |
252 std::terminate(); | |
253 } | |
254 #else | |
255 detach(); | |
256 #endif | |
257 } | |
258 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
259 template < | |
260 class F | |
261 > | |
262 explicit thread(BOOST_THREAD_RV_REF(F) f | |
263 //, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0 | |
264 ): | |
265 thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f)))) | |
266 { | |
267 start_thread(); | |
268 } | |
269 template < | |
270 class F | |
271 > | |
272 thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f): | |
273 thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f)))) | |
274 { | |
275 start_thread(attrs); | |
276 } | |
277 | |
278 #else | |
279 #ifdef BOOST_NO_SFINAE | |
280 template <class F> | |
281 explicit thread(F f): | |
282 thread_info(make_thread_info(f)) | |
283 { | |
284 start_thread(); | |
285 } | |
286 template <class F> | |
287 thread(attributes const& attrs, F f): | |
288 thread_info(make_thread_info(f)) | |
289 { | |
290 start_thread(attrs); | |
291 } | |
292 #else | |
293 template <class F> | |
294 explicit thread(F f | |
295 , typename disable_if_c< | |
296 boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value | |
297 //|| is_same<typename decay<F>::type, thread>::value | |
298 , dummy* >::type=0 | |
299 ): | |
300 thread_info(make_thread_info(f)) | |
301 { | |
302 start_thread(); | |
303 } | |
304 template <class F> | |
305 thread(attributes const& attrs, F f | |
306 , typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0 | |
307 ): | |
308 thread_info(make_thread_info(f)) | |
309 { | |
310 start_thread(attrs); | |
311 } | |
312 #endif | |
313 template <class F> | |
314 explicit thread(BOOST_THREAD_RV_REF(F) f | |
315 , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0 | |
316 ): | |
317 #ifdef BOOST_THREAD_USES_MOVE | |
318 thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward | |
319 #else | |
320 thread_info(make_thread_info(f)) // todo : Add forward | |
321 #endif | |
322 { | |
323 start_thread(); | |
324 } | |
325 | |
326 template <class F> | |
327 thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f): | |
328 #ifdef BOOST_THREAD_USES_MOVE | |
329 thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward | |
330 #else | |
331 thread_info(make_thread_info(f)) // todo : Add forward | |
332 #endif | |
333 { | |
334 start_thread(attrs); | |
335 } | |
336 #endif | |
337 thread(BOOST_THREAD_RV_REF(thread) x) | |
338 { | |
339 thread_info=BOOST_THREAD_RV(x).thread_info; | |
340 BOOST_THREAD_RV(x).thread_info.reset(); | |
341 } | |
342 #if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. | |
343 #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) | |
344 thread& operator=(thread x) | |
345 { | |
346 swap(x); | |
347 return *this; | |
348 } | |
349 #endif | |
350 #endif | |
351 | |
352 thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT | |
353 { | |
354 | |
355 #if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE | |
356 if (joinable()) std::terminate(); | |
357 #endif | |
358 thread_info=BOOST_THREAD_RV(other).thread_info; | |
359 BOOST_THREAD_RV(other).thread_info.reset(); | |
360 return *this; | |
361 } | |
362 | |
363 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) | |
364 template <class F, class Arg, class ...Args> | |
365 thread(F&& f, Arg&& arg, Args&&... args) : | |
366 thread_info(make_thread_info( | |
367 thread_detail::decay_copy(boost::forward<F>(f)), | |
368 thread_detail::decay_copy(boost::forward<Arg>(arg)), | |
369 thread_detail::decay_copy(boost::forward<Args>(args))...) | |
370 ) | |
371 | |
372 { | |
373 start_thread(); | |
374 } | |
375 template <class F, class Arg, class ...Args> | |
376 thread(attributes const& attrs, F&& f, Arg&& arg, Args&&... args) : | |
377 thread_info(make_thread_info( | |
378 thread_detail::decay_copy(boost::forward<F>(f)), | |
379 thread_detail::decay_copy(boost::forward<Arg>(arg)), | |
380 thread_detail::decay_copy(boost::forward<Args>(args))...) | |
381 ) | |
382 | |
383 { | |
384 start_thread(attrs); | |
385 } | |
386 #else | |
387 template <class F,class A1> | |
388 thread(F f,A1 a1,typename disable_if<boost::thread_detail::is_convertible<F&,thread_attributes >, dummy* >::type=0): | |
389 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1))) | |
390 { | |
391 start_thread(); | |
392 } | |
393 template <class F,class A1,class A2> | |
394 thread(F f,A1 a1,A2 a2): | |
395 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2))) | |
396 { | |
397 start_thread(); | |
398 } | |
399 | |
400 template <class F,class A1,class A2,class A3> | |
401 thread(F f,A1 a1,A2 a2,A3 a3): | |
402 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3))) | |
403 { | |
404 start_thread(); | |
405 } | |
406 | |
407 template <class F,class A1,class A2,class A3,class A4> | |
408 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4): | |
409 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4))) | |
410 { | |
411 start_thread(); | |
412 } | |
413 | |
414 template <class F,class A1,class A2,class A3,class A4,class A5> | |
415 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5): | |
416 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5))) | |
417 { | |
418 start_thread(); | |
419 } | |
420 | |
421 template <class F,class A1,class A2,class A3,class A4,class A5,class A6> | |
422 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6): | |
423 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6))) | |
424 { | |
425 start_thread(); | |
426 } | |
427 | |
428 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7> | |
429 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7): | |
430 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7))) | |
431 { | |
432 start_thread(); | |
433 } | |
434 | |
435 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8> | |
436 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8): | |
437 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8))) | |
438 { | |
439 start_thread(); | |
440 } | |
441 | |
442 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9> | |
443 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9): | |
444 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9))) | |
445 { | |
446 start_thread(); | |
447 } | |
448 #endif | |
449 void swap(thread& x) BOOST_NOEXCEPT | |
450 { | |
451 thread_info.swap(x.thread_info); | |
452 } | |
453 | |
454 class id; | |
455 #ifdef BOOST_THREAD_PLATFORM_PTHREAD | |
456 inline id get_id() const BOOST_NOEXCEPT; | |
457 #else | |
458 id get_id() const BOOST_NOEXCEPT; | |
459 #endif | |
460 | |
461 | |
462 bool joinable() const BOOST_NOEXCEPT; | |
463 private: | |
464 bool join_noexcept(); | |
465 public: | |
466 inline void join(); | |
467 | |
468 #ifdef BOOST_THREAD_USES_CHRONO | |
469 template <class Rep, class Period> | |
470 bool try_join_for(const chrono::duration<Rep, Period>& rel_time) | |
471 { | |
472 return try_join_until(chrono::steady_clock::now() + rel_time); | |
473 } | |
474 template <class Clock, class Duration> | |
475 bool try_join_until(const chrono::time_point<Clock, Duration>& t) | |
476 { | |
477 using namespace chrono; | |
478 system_clock::time_point s_now = system_clock::now(); | |
479 bool joined= false; | |
480 do { | |
481 typename Clock::duration d = ceil<nanoseconds>(t-Clock::now()); | |
482 if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached | |
483 joined = try_join_until(s_now + d); | |
484 } while (! joined); | |
485 return true; | |
486 } | |
487 template <class Duration> | |
488 bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t) | |
489 { | |
490 using namespace chrono; | |
491 typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; | |
492 return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); | |
493 } | |
494 #endif | |
495 #if defined(BOOST_THREAD_PLATFORM_WIN32) | |
496 private: | |
497 bool do_try_join_until_noexcept(uintmax_t milli, bool& res); | |
498 inline bool do_try_join_until(uintmax_t milli); | |
499 public: | |
500 bool timed_join(const system_time& abs_time); | |
501 //{ | |
502 // return do_try_join_until(get_milliseconds_until(wait_until)); | |
503 //} | |
504 | |
505 #ifdef BOOST_THREAD_USES_CHRONO | |
506 bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) | |
507 { | |
508 chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now()); | |
509 return do_try_join_until(rel_time.count()); | |
510 } | |
511 #endif | |
512 | |
513 | |
514 #else | |
515 private: | |
516 bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res); | |
517 inline bool do_try_join_until(struct timespec const &timeout); | |
518 public: | |
519 #if defined BOOST_THREAD_USES_DATETIME | |
520 bool timed_join(const system_time& abs_time) | |
521 { | |
522 struct timespec const ts=detail::to_timespec(abs_time); | |
523 return do_try_join_until(ts); | |
524 } | |
525 #endif | |
526 #ifdef BOOST_THREAD_USES_CHRONO | |
527 bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) | |
528 { | |
529 using namespace chrono; | |
530 nanoseconds d = tp.time_since_epoch(); | |
531 timespec ts = boost::detail::to_timespec(d); | |
532 return do_try_join_until(ts); | |
533 } | |
534 #endif | |
535 | |
536 #endif | |
537 public: | |
538 | |
539 #if defined BOOST_THREAD_USES_DATETIME | |
540 template<typename TimeDuration> | |
541 inline bool timed_join(TimeDuration const& rel_time) | |
542 { | |
543 return timed_join(get_system_time()+rel_time); | |
544 } | |
545 #endif | |
546 void detach(); | |
547 | |
548 static unsigned hardware_concurrency() BOOST_NOEXCEPT; | |
549 | |
550 #define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE | |
551 typedef detail::thread_data_base::native_handle_type native_handle_type; | |
552 native_handle_type native_handle(); | |
553 | |
554 #if defined BOOST_THREAD_PROVIDES_THREAD_EQ | |
555 // Use thread::id when comparisions are needed | |
556 // backwards compatibility | |
557 bool operator==(const thread& other) const; | |
558 bool operator!=(const thread& other) const; | |
559 #endif | |
560 #if defined BOOST_THREAD_USES_DATETIME | |
561 static inline void yield() BOOST_NOEXCEPT | |
562 { | |
563 this_thread::yield(); | |
564 } | |
565 | |
566 static inline void sleep(const system_time& xt) | |
567 { | |
568 this_thread::sleep(xt); | |
569 } | |
570 #endif | |
571 | |
572 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
573 // extensions | |
574 void interrupt(); | |
575 bool interruption_requested() const BOOST_NOEXCEPT; | |
576 #endif | |
577 }; | |
578 | |
579 inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT | |
580 { | |
581 return lhs.swap(rhs); | |
582 } | |
583 | |
584 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
585 inline thread&& move(thread& t) BOOST_NOEXCEPT | |
586 { | |
587 return static_cast<thread&&>(t); | |
588 } | |
589 #endif | |
590 | |
591 BOOST_THREAD_DCL_MOVABLE(thread) | |
592 | |
593 namespace this_thread | |
594 { | |
595 #ifdef BOOST_THREAD_PLATFORM_PTHREAD | |
596 inline thread::id get_id() BOOST_NOEXCEPT; | |
597 #else | |
598 thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT; | |
599 #endif | |
600 | |
601 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
602 void BOOST_THREAD_DECL interruption_point(); | |
603 bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT; | |
604 bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT; | |
605 #endif | |
606 | |
607 #if defined BOOST_THREAD_USES_DATETIME | |
608 inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time) | |
609 { | |
610 sleep(system_time(abs_time)); | |
611 } | |
612 #endif | |
613 } | |
614 | |
615 class BOOST_SYMBOL_VISIBLE thread::id | |
616 { | |
617 private: | |
618 friend inline | |
619 std::size_t | |
620 hash_value(const thread::id &v) | |
621 { | |
622 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID | |
623 return hash_value(v.thread_data); | |
624 #else | |
625 return hash_value(v.thread_data.get()); | |
626 #endif | |
627 } | |
628 | |
629 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID | |
630 #if defined(BOOST_THREAD_PLATFORM_WIN32) | |
631 typedef unsigned int data; | |
632 #else | |
633 typedef thread::native_handle_type data; | |
634 #endif | |
635 #else | |
636 typedef detail::thread_data_ptr data; | |
637 #endif | |
638 data thread_data; | |
639 | |
640 id(data thread_data_): | |
641 thread_data(thread_data_) | |
642 {} | |
643 friend class thread; | |
644 friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT; | |
645 public: | |
646 id() BOOST_NOEXCEPT: | |
647 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID | |
648 thread_data(0) | |
649 #else | |
650 thread_data() | |
651 #endif | |
652 {} | |
653 | |
654 id(const id& other) BOOST_NOEXCEPT : | |
655 thread_data(other.thread_data) | |
656 {} | |
657 | |
658 bool operator==(const id& y) const BOOST_NOEXCEPT | |
659 { | |
660 return thread_data==y.thread_data; | |
661 } | |
662 | |
663 bool operator!=(const id& y) const BOOST_NOEXCEPT | |
664 { | |
665 return thread_data!=y.thread_data; | |
666 } | |
667 | |
668 bool operator<(const id& y) const BOOST_NOEXCEPT | |
669 { | |
670 return thread_data<y.thread_data; | |
671 } | |
672 | |
673 bool operator>(const id& y) const BOOST_NOEXCEPT | |
674 { | |
675 return y.thread_data<thread_data; | |
676 } | |
677 | |
678 bool operator<=(const id& y) const BOOST_NOEXCEPT | |
679 { | |
680 return !(y.thread_data<thread_data); | |
681 } | |
682 | |
683 bool operator>=(const id& y) const BOOST_NOEXCEPT | |
684 { | |
685 return !(thread_data<y.thread_data); | |
686 } | |
687 | |
688 #ifndef BOOST_NO_IOSTREAM | |
689 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS | |
690 template<class charT, class traits> | |
691 friend BOOST_SYMBOL_VISIBLE | |
692 std::basic_ostream<charT, traits>& | |
693 operator<<(std::basic_ostream<charT, traits>& os, const id& x) | |
694 { | |
695 if(x.thread_data) | |
696 { | |
697 io::ios_flags_saver ifs( os ); | |
698 return os<< std::hex << x.thread_data; | |
699 } | |
700 else | |
701 { | |
702 return os<<"{Not-any-thread}"; | |
703 } | |
704 } | |
705 #else | |
706 template<class charT, class traits> | |
707 BOOST_SYMBOL_VISIBLE | |
708 std::basic_ostream<charT, traits>& | |
709 print(std::basic_ostream<charT, traits>& os) const | |
710 { | |
711 if(thread_data) | |
712 { | |
713 io::ios_flags_saver ifs( os ); | |
714 return os<< std::hex << thread_data; | |
715 } | |
716 else | |
717 { | |
718 return os<<"{Not-any-thread}"; | |
719 } | |
720 } | |
721 | |
722 #endif | |
723 #endif | |
724 }; | |
725 | |
726 #ifdef BOOST_THREAD_PLATFORM_PTHREAD | |
727 thread::id thread::get_id() const BOOST_NOEXCEPT | |
728 { | |
729 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID | |
730 return const_cast<thread*>(this)->native_handle(); | |
731 #else | |
732 detail::thread_data_ptr const local_thread_info=(get_thread_info)(); | |
733 return (local_thread_info? id(local_thread_info) : id()); | |
734 #endif | |
735 } | |
736 | |
737 namespace this_thread | |
738 { | |
739 inline thread::id get_id() BOOST_NOEXCEPT | |
740 { | |
741 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID | |
742 return pthread_self(); | |
743 #else | |
744 boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data(); | |
745 return (thread_info?thread::id(thread_info->shared_from_this()):thread::id()); | |
746 #endif | |
747 } | |
748 } | |
749 #endif | |
750 void thread::join() { | |
751 if (this_thread::get_id() == get_id()) | |
752 boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); | |
753 | |
754 BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(), | |
755 thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable") | |
756 ); | |
757 } | |
758 | |
759 #ifdef BOOST_THREAD_PLATFORM_PTHREAD | |
760 bool thread::do_try_join_until(struct timespec const &timeout) | |
761 #else | |
762 bool thread::do_try_join_until(uintmax_t timeout) | |
763 #endif | |
764 { | |
765 if (this_thread::get_id() == get_id()) | |
766 boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); | |
767 bool res; | |
768 if (do_try_join_until_noexcept(timeout, res)) | |
769 { | |
770 return res; | |
771 } | |
772 else | |
773 { | |
774 BOOST_THREAD_THROW_ELSE_RETURN( | |
775 (thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")), | |
776 false | |
777 ); | |
778 } | |
779 } | |
780 | |
781 #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) | |
782 template<class charT, class traits> | |
783 BOOST_SYMBOL_VISIBLE | |
784 std::basic_ostream<charT, traits>& | |
785 operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x) | |
786 { | |
787 return x.print(os); | |
788 } | |
789 #endif | |
790 | |
791 #if defined BOOST_THREAD_PROVIDES_THREAD_EQ | |
792 inline bool thread::operator==(const thread& other) const | |
793 { | |
794 return get_id()==other.get_id(); | |
795 } | |
796 | |
797 inline bool thread::operator!=(const thread& other) const | |
798 { | |
799 return get_id()!=other.get_id(); | |
800 } | |
801 #endif | |
802 | |
803 namespace detail | |
804 { | |
805 struct thread_exit_function_base | |
806 { | |
807 virtual ~thread_exit_function_base() | |
808 {} | |
809 virtual void operator()()=0; | |
810 }; | |
811 | |
812 template<typename F> | |
813 struct thread_exit_function: | |
814 thread_exit_function_base | |
815 { | |
816 F f; | |
817 | |
818 thread_exit_function(F f_): | |
819 f(f_) | |
820 {} | |
821 | |
822 void operator()() | |
823 { | |
824 f(); | |
825 } | |
826 }; | |
827 | |
828 void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*); | |
829 struct shared_state_base; | |
830 #if defined(BOOST_THREAD_PLATFORM_WIN32) | |
831 inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as) | |
832 { | |
833 detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); | |
834 if(current_thread_data) | |
835 { | |
836 current_thread_data->make_ready_at_thread_exit(as); | |
837 } | |
838 } | |
839 #else | |
840 void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as); | |
841 #endif | |
842 } | |
843 | |
844 namespace this_thread | |
845 { | |
846 template<typename F> | |
847 void at_thread_exit(F f) | |
848 { | |
849 detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f); | |
850 detail::add_thread_exit_function(thread_exit_func); | |
851 } | |
852 } | |
853 } | |
854 | |
855 #ifdef BOOST_MSVC | |
856 #pragma warning(pop) | |
857 #endif | |
858 | |
859 #include <boost/config/abi_suffix.hpp> | |
860 | |
861 #endif |