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-8 Anthony Williams
8 #include <boost/thread/exceptions.hpp>
10 #include <boost/thread/detail/move.hpp>
11 #include <boost/thread/mutex.hpp>
12 #include <boost/thread/xtime.hpp>
13 #include <boost/thread/detail/thread_heap_alloc.hpp>
14 #include <boost/utility.hpp>
15 #include <boost/assert.hpp>
18 #include <boost/ref.hpp>
19 #include <boost/cstdint.hpp>
20 #include <boost/bind.hpp>
23 #include <boost/utility/enable_if.hpp>
24 #include <boost/type_traits/remove_reference.hpp>
26 #include <boost/config/abi_prefix.hpp>
30 #pragma warning(disable:4251)
39 public detail::thread_data_base
42 #ifdef BOOST_HAS_RVALUE_REFS
44 f(static_cast<F
&&>(f_
))
50 thread_data(detail::thread_move_t
<F
> f_
):
61 void operator=(thread_data
&);
62 thread_data(thread_data
&);
66 class thread_data
<boost::reference_wrapper
<F
> >:
67 public detail::thread_data_base
72 void operator=(thread_data
&);
73 thread_data(thread_data
&);
75 thread_data(boost::reference_wrapper
<F
> f_
):
86 class thread_data
<const boost::reference_wrapper
<F
> >:
87 public detail::thread_data_base
91 void operator=(thread_data
&);
92 thread_data(thread_data
&);
94 thread_data(const boost::reference_wrapper
<F
> f_
):
105 class BOOST_THREAD_DECL thread
109 thread
& operator=(thread
&);
111 void release_handle();
113 mutable boost::mutex thread_info_mutex
;
114 detail::thread_data_ptr thread_info
;
118 explicit thread(detail::thread_data_ptr data
);
120 detail::thread_data_ptr
get_thread_info() const;
122 #ifdef BOOST_HAS_RVALUE_REFS
124 static inline detail::thread_data_ptr
make_thread_info(F
&& f
)
126 return detail::thread_data_ptr(detail::heap_new
<detail::thread_data
<typename
boost::remove_reference
<F
>::type
> >(static_cast<F
&&>(f
)));
128 static inline detail::thread_data_ptr
make_thread_info(void (*f
)())
130 return detail::thread_data_ptr(detail::heap_new
<detail::thread_data
<void(*)()> >(f
));
134 static inline detail::thread_data_ptr
make_thread_info(F f
)
136 return detail::thread_data_ptr(detail::heap_new
<detail::thread_data
<F
> >(f
));
139 static inline detail::thread_data_ptr
make_thread_info(boost::detail::thread_move_t
<F
> f
)
141 return detail::thread_data_ptr(detail::heap_new
<detail::thread_data
<F
> >(f
));
150 #ifdef BOOST_HAS_RVALUE_REFS
153 thread_info(make_thread_info(static_cast<F
&&>(f
)))
158 thread(thread
&& other
)
160 thread_info
.swap(other
.thread_info
);
163 thread
& operator=(thread
&& other
)
165 thread_info
=other
.thread_info
;
166 other
.thread_info
.reset();
172 return static_cast<thread
&&>(*this);
176 #ifdef BOOST_NO_SFINAE
178 explicit thread(F f
):
179 thread_info(make_thread_info(f
))
185 explicit thread(F f
,typename disable_if
<boost::is_convertible
<F
&,detail::thread_move_t
<F
> >, dummy
* >::type
=0):
186 thread_info(make_thread_info(f
))
193 explicit thread(detail::thread_move_t
<F
> f
):
194 thread_info(make_thread_info(f
))
199 thread(detail::thread_move_t
<thread
> x
)
201 thread_info
=x
->thread_info
;
202 x
->thread_info
.reset();
205 thread
& operator=(detail::thread_move_t
<thread
> x
)
207 thread
new_thread(x
);
212 operator detail::thread_move_t
<thread
>()
217 detail::thread_move_t
<thread
> move()
219 detail::thread_move_t
<thread
> x(*this);
225 template <class F
,class A1
>
227 thread_info(make_thread_info(boost::bind(boost::type
<void>(),f
,a1
)))
231 template <class F
,class A1
,class A2
>
232 thread(F f
,A1 a1
,A2 a2
):
233 thread_info(make_thread_info(boost::bind(boost::type
<void>(),f
,a1
,a2
)))
238 template <class F
,class A1
,class A2
,class A3
>
239 thread(F f
,A1 a1
,A2 a2
,A3 a3
):
240 thread_info(make_thread_info(boost::bind(boost::type
<void>(),f
,a1
,a2
,a3
)))
245 template <class F
,class A1
,class A2
,class A3
,class A4
>
246 thread(F f
,A1 a1
,A2 a2
,A3 a3
,A4 a4
):
247 thread_info(make_thread_info(boost::bind(boost::type
<void>(),f
,a1
,a2
,a3
,a4
)))
252 template <class F
,class A1
,class A2
,class A3
,class A4
,class A5
>
253 thread(F f
,A1 a1
,A2 a2
,A3 a3
,A4 a4
,A5 a5
):
254 thread_info(make_thread_info(boost::bind(boost::type
<void>(),f
,a1
,a2
,a3
,a4
,a5
)))
259 template <class F
,class A1
,class A2
,class A3
,class A4
,class A5
,class A6
>
260 thread(F f
,A1 a1
,A2 a2
,A3 a3
,A4 a4
,A5 a5
,A6 a6
):
261 thread_info(make_thread_info(boost::bind(boost::type
<void>(),f
,a1
,a2
,a3
,a4
,a5
,a6
)))
266 template <class F
,class A1
,class A2
,class A3
,class A4
,class A5
,class A6
,class A7
>
267 thread(F f
,A1 a1
,A2 a2
,A3 a3
,A4 a4
,A5 a5
,A6 a6
,A7 a7
):
268 thread_info(make_thread_info(boost::bind(boost::type
<void>(),f
,a1
,a2
,a3
,a4
,a5
,a6
,a7
)))
273 template <class F
,class A1
,class A2
,class A3
,class A4
,class A5
,class A6
,class A7
,class A8
>
274 thread(F f
,A1 a1
,A2 a2
,A3 a3
,A4 a4
,A5 a5
,A6 a6
,A7 a7
,A8 a8
):
275 thread_info(make_thread_info(boost::bind(boost::type
<void>(),f
,a1
,a2
,a3
,a4
,a5
,a6
,a7
,a8
)))
280 template <class F
,class A1
,class A2
,class A3
,class A4
,class A5
,class A6
,class A7
,class A8
,class A9
>
281 thread(F f
,A1 a1
,A2 a2
,A3 a3
,A4 a4
,A5 a5
,A6 a6
,A7 a7
,A8 a8
,A9 a9
):
282 thread_info(make_thread_info(boost::bind(boost::type
<void>(),f
,a1
,a2
,a3
,a4
,a5
,a6
,a7
,a8
,a9
)))
289 thread_info
.swap(x
.thread_info
);
296 bool joinable() const;
298 bool timed_join(const system_time
& wait_until
);
300 template<typename TimeDuration
>
301 inline bool timed_join(TimeDuration
const& rel_time
)
303 return timed_join(get_system_time()+rel_time
);
307 static unsigned hardware_concurrency();
309 typedef detail::thread_data_base::native_handle_type native_handle_type
;
310 native_handle_type
native_handle();
312 // backwards compatibility
313 bool operator==(const thread
& other
) const;
314 bool operator!=(const thread
& other
) const;
316 static inline void yield()
318 this_thread::yield();
321 static inline void sleep(const system_time
& xt
)
323 this_thread::sleep(xt
);
328 bool interruption_requested() const;
331 inline void swap(thread
& lhs
,thread
& rhs
)
333 return lhs
.swap(rhs
);
336 #ifdef BOOST_HAS_RVALUE_REFS
337 inline thread
&& move(thread
&& t
)
342 inline thread
move(detail::thread_move_t
<thread
> t
)
348 namespace this_thread
350 class BOOST_THREAD_DECL disable_interruption
352 disable_interruption(const disable_interruption
&);
353 disable_interruption
& operator=(const disable_interruption
&);
355 bool interruption_was_enabled
;
356 friend class restore_interruption
;
358 disable_interruption();
359 ~disable_interruption();
362 class BOOST_THREAD_DECL restore_interruption
364 restore_interruption(const restore_interruption
&);
365 restore_interruption
& operator=(const restore_interruption
&);
367 explicit restore_interruption(disable_interruption
& d
);
368 ~restore_interruption();
371 thread::id BOOST_THREAD_DECL
get_id();
373 void BOOST_THREAD_DECL
interruption_point();
374 bool BOOST_THREAD_DECL
interruption_enabled();
375 bool BOOST_THREAD_DECL
interruption_requested();
377 inline void sleep(xtime
const& abs_time
)
379 sleep(system_time(abs_time
));
386 detail::thread_data_ptr thread_data
;
388 id(detail::thread_data_ptr thread_data_
):
389 thread_data(thread_data_
)
392 friend id
this_thread::get_id();
398 bool operator==(const id
& y
) const
400 return thread_data
==y
.thread_data
;
403 bool operator!=(const id
& y
) const
405 return thread_data
!=y
.thread_data
;
408 bool operator<(const id
& y
) const
410 return thread_data
<y
.thread_data
;
413 bool operator>(const id
& y
) const
415 return y
.thread_data
<thread_data
;
418 bool operator<=(const id
& y
) const
420 return !(y
.thread_data
<thread_data
);
423 bool operator>=(const id
& y
) const
425 return !(thread_data
<y
.thread_data
);
428 template<class charT
, class traits
>
429 friend std::basic_ostream
<charT
, traits
>&
430 operator<<(std::basic_ostream
<charT
, traits
>& os
, const id
& x
)
434 return os
<<x
.thread_data
;
438 return os
<<"{Not-any-thread}";
443 inline bool thread::operator==(const thread
& other
) const
445 return get_id()==other
.get_id();
448 inline bool thread::operator!=(const thread
& other
) const
450 return get_id()!=other
.get_id();
455 struct thread_exit_function_base
457 virtual ~thread_exit_function_base()
459 virtual void operator()() const=0;
463 struct thread_exit_function
:
464 thread_exit_function_base
468 thread_exit_function(F f_
):
472 void operator()() const
478 void add_thread_exit_function(thread_exit_function_base
*);
481 namespace this_thread
484 void at_thread_exit(F f
)
486 detail::thread_exit_function_base
* const thread_exit_func
=detail::heap_new
<detail::thread_exit_function
<F
> >(f
);
487 detail::add_thread_exit_function(thread_exit_func
);
497 for(std::list
<thread
*>::iterator it
=threads
.begin(),end
=threads
.end();
506 thread
* create_thread(F threadfunc
)
508 boost::lock_guard
<mutex
> guard(m
);
509 std::auto_ptr
<thread
> new_thread(new thread(threadfunc
));
510 threads
.push_back(new_thread
.get());
511 return new_thread
.release();
514 void add_thread(thread
* thrd
)
518 boost::lock_guard
<mutex
> guard(m
);
519 threads
.push_back(thrd
);
523 void remove_thread(thread
* thrd
)
525 boost::lock_guard
<mutex
> guard(m
);
526 std::list
<thread
*>::iterator
const it
=std::find(threads
.begin(),threads
.end(),thrd
);
527 if(it
!=threads
.end())
535 boost::lock_guard
<mutex
> guard(m
);
537 for(std::list
<thread
*>::iterator it
=threads
.begin(),end
=threads
.end();
547 boost::lock_guard
<mutex
> guard(m
);
549 for(std::list
<thread
*>::iterator it
=threads
.begin(),end
=threads
.end();
559 boost::lock_guard
<mutex
> guard(m
);
560 return threads
.size();
564 std::list
<thread
*> threads
;
573 #include <boost/config/abi_suffix.hpp>