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