fix doc example typo
[boost.git] / boost / thread / detail / thread.hpp
blobfbb895d17062c7ffa22af5a87452578b30844a53
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>
9 #include <ostream>
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>
16 #include <list>
17 #include <algorithm>
18 #include <boost/ref.hpp>
19 #include <boost/cstdint.hpp>
20 #include <boost/bind.hpp>
21 #include <stdlib.h>
22 #include <memory>
23 #include <boost/utility/enable_if.hpp>
24 #include <boost/type_traits/remove_reference.hpp>
26 #include <boost/config/abi_prefix.hpp>
28 #ifdef BOOST_MSVC
29 #pragma warning(push)
30 #pragma warning(disable:4251)
31 #endif
33 namespace boost
35 namespace detail
37 template<typename F>
38 class thread_data:
39 public detail::thread_data_base
41 public:
42 #ifdef BOOST_HAS_RVALUE_REFS
43 thread_data(F&& f_):
44 f(static_cast<F&&>(f_))
46 #else
47 thread_data(F f_):
48 f(f_)
50 thread_data(detail::thread_move_t<F> f_):
51 f(f_)
53 #endif
54 void run()
56 f();
58 private:
59 F f;
61 void operator=(thread_data&);
62 thread_data(thread_data&);
65 template<typename F>
66 class thread_data<boost::reference_wrapper<F> >:
67 public detail::thread_data_base
69 private:
70 F& f;
72 void operator=(thread_data&);
73 thread_data(thread_data&);
74 public:
75 thread_data(boost::reference_wrapper<F> f_):
76 f(f_)
79 void run()
81 f();
85 template<typename F>
86 class thread_data<const boost::reference_wrapper<F> >:
87 public detail::thread_data_base
89 private:
90 F& f;
91 void operator=(thread_data&);
92 thread_data(thread_data&);
93 public:
94 thread_data(const boost::reference_wrapper<F> f_):
95 f(f_)
98 void run()
100 f();
105 class BOOST_THREAD_DECL thread
107 private:
108 thread(thread&);
109 thread& operator=(thread&);
111 void release_handle();
113 mutable boost::mutex thread_info_mutex;
114 detail::thread_data_ptr thread_info;
116 void start_thread();
118 explicit thread(detail::thread_data_ptr data);
120 detail::thread_data_ptr get_thread_info() const;
122 #ifdef BOOST_HAS_RVALUE_REFS
123 template<typename F>
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));
132 #else
133 template<typename 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));
138 template<typename 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));
144 struct dummy;
145 #endif
146 public:
147 thread();
148 ~thread();
150 #ifdef BOOST_HAS_RVALUE_REFS
151 template <class F>
152 thread(F&& f):
153 thread_info(make_thread_info(static_cast<F&&>(f)))
155 start_thread();
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();
167 return *this;
170 thread&& move()
172 return static_cast<thread&&>(*this);
175 #else
176 #ifdef BOOST_NO_SFINAE
177 template <class F>
178 explicit thread(F f):
179 thread_info(make_thread_info(f))
181 start_thread();
183 #else
184 template <class 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))
188 start_thread();
190 #endif
192 template <class F>
193 explicit thread(detail::thread_move_t<F> f):
194 thread_info(make_thread_info(f))
196 start_thread();
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);
208 swap(new_thread);
209 return *this;
212 operator detail::thread_move_t<thread>()
214 return move();
217 detail::thread_move_t<thread> move()
219 detail::thread_move_t<thread> x(*this);
220 return x;
223 #endif
225 template <class F,class A1>
226 thread(F f,A1 a1):
227 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
229 start_thread();
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)))
235 start_thread();
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)))
242 start_thread();
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)))
249 start_thread();
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)))
256 start_thread();
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)))
263 start_thread();
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)))
270 start_thread();
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)))
277 start_thread();
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)))
284 start_thread();
287 void swap(thread& x)
289 thread_info.swap(x.thread_info);
292 class id;
293 id get_id() const;
296 bool joinable() const;
297 void join();
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);
305 void detach();
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);
326 // extensions
327 void interrupt();
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)
339 return t;
341 #else
342 inline thread move(detail::thread_move_t<thread> t)
344 return thread(t);
346 #endif
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;
357 public:
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&);
366 public:
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));
383 class thread::id
385 private:
386 detail::thread_data_ptr thread_data;
388 id(detail::thread_data_ptr thread_data_):
389 thread_data(thread_data_)
391 friend class thread;
392 friend id this_thread::get_id();
393 public:
394 id():
395 thread_data()
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)
432 if(x.thread_data)
434 return os<<x.thread_data;
436 else
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();
453 namespace detail
455 struct thread_exit_function_base
457 virtual ~thread_exit_function_base()
459 virtual void operator()() const=0;
462 template<typename F>
463 struct thread_exit_function:
464 thread_exit_function_base
466 F f;
468 thread_exit_function(F f_):
469 f(f_)
472 void operator()() const
474 f();
478 void add_thread_exit_function(thread_exit_function_base*);
481 namespace this_thread
483 template<typename F>
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);
491 class thread_group:
492 private noncopyable
494 public:
495 ~thread_group()
497 for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
498 it!=end;
499 ++it)
501 delete *it;
505 template<typename F>
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)
516 if(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())
529 threads.erase(it);
533 void join_all()
535 boost::lock_guard<mutex> guard(m);
537 for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
538 it!=end;
539 ++it)
541 (*it)->join();
545 void interrupt_all()
547 boost::lock_guard<mutex> guard(m);
549 for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
550 it!=end;
551 ++it)
553 (*it)->interrupt();
557 size_t size() const
559 boost::lock_guard<mutex> guard(m);
560 return threads.size();
563 private:
564 std::list<thread*> threads;
565 mutable mutex m;
569 #ifdef BOOST_MSVC
570 #pragma warning(pop)
571 #endif
573 #include <boost/config/abi_suffix.hpp>
575 #endif