scoped_thread.hpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. // Distributed under the Boost Software License, Version 1.0. (See
  2. // accompanying file LICENSE_1_0.txt or copy at
  3. // http://www.boost.org/LICENSE_1_0.txt)
  4. // (C) Copyright 2009-2012 Anthony Williams
  5. // (C) Copyright 2012 Vicente J. Botet Escriba
  6. // Based on the Anthony's idea of scoped_thread in CCiA
  7. #ifndef BOOST_THREAD_SCOPED_THREAD_HPP
  8. #define BOOST_THREAD_SCOPED_THREAD_HPP
  9. #include <boost/thread/detail/config.hpp>
  10. #include <boost/thread/detail/delete.hpp>
  11. #include <boost/thread/detail/move.hpp>
  12. #include <boost/thread/thread_functors.hpp>
  13. #include <boost/thread/thread_only.hpp>
  14. #include <boost/config/abi_prefix.hpp>
  15. namespace boost
  16. {
  17. /**
  18. * RAI @c thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
  19. *
  20. * CallableThread: A callable void(thread&) .
  21. * The default is a join_if_joinable.
  22. *
  23. * thread std/boost::thread destructor terminates the program if the thread is not joinable.
  24. * Having a wrapper that can join the thread before destroying it seems a natural need.
  25. *
  26. * Example:
  27. *
  28. * boost::strict_scoped_thread<> t((boost::thread(F)));
  29. *
  30. */
  31. template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
  32. class strict_scoped_thread
  33. {
  34. Thread t_;
  35. struct dummy;
  36. public:
  37. BOOST_THREAD_NO_COPYABLE( strict_scoped_thread) /// non copyable
  38. /*
  39. *
  40. */
  41. #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  42. template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type>
  43. explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
  44. t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
  45. #else
  46. template <class F>
  47. explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f,
  48. typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type=0) :
  49. t_(boost::forward<F>(f)) {}
  50. template <class F, class A1>
  51. strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
  52. t_(boost::forward<F>(f), boost::forward<A1>(a1)) {}
  53. template <class F, class A1, class A2>
  54. strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) :
  55. t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2)) {}
  56. template <class F, class A1, class A2, class A3>
  57. strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) :
  58. t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)) {}
  59. #endif
  60. /**
  61. * Constructor from the thread to own.
  62. *
  63. * @param t: the thread to own.
  64. *
  65. * Effects: move the thread to own @c t.
  66. */
  67. explicit strict_scoped_thread(BOOST_THREAD_RV_REF(Thread) t) BOOST_NOEXCEPT :
  68. t_(boost::move(t))
  69. {
  70. }
  71. /**
  72. * Destructor
  73. * Effects: Call the CallableThread functor before destroying the owned thread.
  74. * Remark: The CallableThread should not throw when joining the thread as the scoped variable is on a scope outside the thread function.
  75. */
  76. ~strict_scoped_thread()
  77. {
  78. CallableThread on_destructor;
  79. on_destructor(t_);
  80. }
  81. };
  82. /**
  83. * RAI @c thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
  84. *
  85. * CallableThread: A callable void(thread&) .
  86. * The default is join_if_joinable.
  87. *
  88. * thread std::thread destructor terminates the program if the thread is not joinable.
  89. * Having a wrapper that can join the thread before destroying it seems a natural need.
  90. *
  91. * Remark: @c scoped_thread is not a @c thread as @c thread is not designed to be derived from as a polymorphic type.
  92. * Anyway @c scoped_thread can be used in most of the contexts a @c thread could be used as it has the
  93. * same non-deprecated interface with the exception of the construction.
  94. *
  95. * Example:
  96. *
  97. * boost::scoped_thread<> t((boost::thread(F)));
  98. * t.interrupt();
  99. *
  100. */
  101. template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
  102. class scoped_thread
  103. {
  104. Thread t_;
  105. struct dummy;
  106. public:
  107. typedef typename Thread::id id;
  108. typedef typename Thread::native_handle_type native_handle_type;
  109. BOOST_THREAD_MOVABLE_ONLY( scoped_thread) /// Movable only
  110. /**
  111. * Default Constructor.
  112. *
  113. * Effects: wraps a not-a-thread.
  114. */
  115. scoped_thread() BOOST_NOEXCEPT:
  116. t_()
  117. {
  118. }
  119. /**
  120. *
  121. */
  122. #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  123. template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type>
  124. explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
  125. t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
  126. #else
  127. template <class F>
  128. explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f,
  129. typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type=0) :
  130. t_(boost::forward<F>(f)) {}
  131. template <class F, class A1>
  132. scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
  133. t_(boost::forward<F>(f), boost::forward<A1>(a1)) {}
  134. template <class F, class A1, class A2>
  135. scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) :
  136. t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2)) {}
  137. template <class F, class A1, class A2, class A3>
  138. scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) :
  139. t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)) {}
  140. #endif
  141. /**
  142. * Constructor from the thread to own.
  143. *
  144. * @param t: the thread to own.
  145. *
  146. * Effects: move the thread to own @c t.
  147. */
  148. explicit scoped_thread(BOOST_THREAD_RV_REF(Thread) t) BOOST_NOEXCEPT :
  149. t_(boost::move(t))
  150. {
  151. }
  152. // explicit operator Thread()
  153. // {
  154. // return boost::move(t_);
  155. // }
  156. /**
  157. * Move constructor.
  158. */
  159. scoped_thread(BOOST_RV_REF(scoped_thread) x) BOOST_NOEXCEPT :
  160. t_(boost::move(BOOST_THREAD_RV(x).t_))
  161. {}
  162. /**
  163. * Destructor
  164. *
  165. * Effects: Call the CallableThread functor before destroying the owned thread.
  166. */
  167. ~scoped_thread()
  168. {
  169. CallableThread on_destructor;
  170. on_destructor(t_);
  171. }
  172. /**
  173. * Move assignment.
  174. */
  175. scoped_thread& operator=(BOOST_RV_REF(scoped_thread) x)
  176. {
  177. CallableThread on_destructor;
  178. on_destructor(t_);
  179. t_ = boost::move(BOOST_THREAD_RV(x).t_);
  180. return *this;
  181. }
  182. /**
  183. *
  184. */
  185. void swap(scoped_thread& x) BOOST_NOEXCEPT
  186. {
  187. t_.swap(x.t_);
  188. }
  189. // forwarded thread functions
  190. inline id get_id() const BOOST_NOEXCEPT
  191. {
  192. return t_.get_id();
  193. }
  194. void detach()
  195. {
  196. t_.detach();
  197. }
  198. void join()
  199. {
  200. t_.join();
  201. }
  202. #ifdef BOOST_THREAD_USES_CHRONO
  203. template <class Rep, class Period>
  204. bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
  205. {
  206. return t_.try_join_for(rel_time);
  207. }
  208. template <class Clock, class Duration>
  209. bool try_join_until(const chrono::time_point<Clock, Duration>& abs_time)
  210. {
  211. return t_.try_join_until(abs_time);
  212. }
  213. #endif
  214. native_handle_type native_handle()BOOST_NOEXCEPT
  215. {
  216. return t_.native_handle();
  217. }
  218. bool joinable() const BOOST_NOEXCEPT
  219. {
  220. return t_.joinable();
  221. }
  222. #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  223. void interrupt()
  224. {
  225. t_.interrupt();
  226. }
  227. bool interruption_requested() const BOOST_NOEXCEPT
  228. {
  229. return t_.interruption_requested();
  230. }
  231. #endif
  232. static unsigned hardware_concurrency() BOOST_NOEXCEPT
  233. {
  234. return Thread::hardware_concurrency();
  235. }
  236. #ifdef BOOST_THREAD_PROVIDES_PHYSICAL_CONCURRENCY
  237. static unsigned physical_concurrency() BOOST_NOEXCEPT
  238. {
  239. return Thread::physical_concurrency();
  240. }
  241. #endif
  242. };
  243. /**
  244. * Effects: swaps the contents of two scoped threads.
  245. */
  246. template <class Destroyer, class Thread >
  247. void swap(scoped_thread<Destroyer, Thread>& lhs, scoped_thread<Destroyer, Thread>& rhs)
  248. BOOST_NOEXCEPT {
  249. return lhs.swap(rhs);
  250. }
  251. typedef scoped_thread<> joining_thread;
  252. }
  253. #include <boost/config/abi_suffix.hpp>
  254. #endif