barrier.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // Copyright (C) 2002-2003
  2. // David Moore, William E. Kempf
  3. // Copyright (C) 2007-8 Anthony Williams
  4. // (C) Copyright 2013 Vicente J. Botet Escriba
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_BARRIER_JDM030602_HPP
  9. #define BOOST_BARRIER_JDM030602_HPP
  10. #include <boost/thread/detail/config.hpp>
  11. #include <boost/thread/detail/delete.hpp>
  12. #include <boost/throw_exception.hpp>
  13. #include <boost/thread/mutex.hpp>
  14. #include <boost/thread/lock_types.hpp>
  15. #include <boost/thread/condition_variable.hpp>
  16. #include <string>
  17. #include <stdexcept>
  18. #include <boost/thread/detail/nullary_function.hpp>
  19. #include <boost/type_traits/is_same.hpp>
  20. #include <boost/type_traits/is_void.hpp>
  21. #include <boost/core/enable_if.hpp>
  22. #include <boost/utility/result_of.hpp>
  23. #include <boost/config/abi_prefix.hpp>
  24. namespace boost
  25. {
  26. namespace thread_detail
  27. {
  28. typedef detail::nullary_function<void()> void_completion_function;
  29. typedef detail::nullary_function<size_t()> size_completion_function;
  30. struct default_barrier_reseter
  31. {
  32. unsigned int size_;
  33. default_barrier_reseter(unsigned int size) :
  34. size_(size)
  35. {
  36. }
  37. BOOST_THREAD_MOVABLE(default_barrier_reseter)
  38. //BOOST_THREAD_COPYABLE_AND_MOVABLE(default_barrier_reseter)
  39. default_barrier_reseter(default_barrier_reseter const& other) BOOST_NOEXCEPT :
  40. size_(other.size_)
  41. {
  42. }
  43. default_barrier_reseter(BOOST_THREAD_RV_REF(default_barrier_reseter) other) BOOST_NOEXCEPT :
  44. size_(BOOST_THREAD_RV(other).size_)
  45. {
  46. }
  47. unsigned int operator()()
  48. {
  49. return size_;
  50. }
  51. };
  52. struct void_functor_barrier_reseter
  53. {
  54. unsigned int size_;
  55. void_completion_function fct_;
  56. template <typename F>
  57. void_functor_barrier_reseter(unsigned int size, BOOST_THREAD_RV_REF(F) funct)
  58. : size_(size), fct_(boost::move(funct))
  59. {}
  60. template <typename F>
  61. void_functor_barrier_reseter(unsigned int size, F& funct)
  62. : size_(size), fct_(funct)
  63. {}
  64. BOOST_THREAD_MOVABLE(void_functor_barrier_reseter)
  65. //BOOST_THREAD_COPYABLE_AND_MOVABLE(void_functor_barrier_reseter)
  66. void_functor_barrier_reseter(void_functor_barrier_reseter const& other) BOOST_NOEXCEPT :
  67. size_(other.size_), fct_(other.fct_)
  68. {
  69. }
  70. void_functor_barrier_reseter(BOOST_THREAD_RV_REF(void_functor_barrier_reseter) other) BOOST_NOEXCEPT :
  71. size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
  72. //size_(BOOST_THREAD_RV(other).size_), fct_(boost::move(BOOST_THREAD_RV(other).fct_))
  73. {
  74. }
  75. unsigned int operator()()
  76. {
  77. fct_();
  78. return size_;
  79. }
  80. };
  81. struct void_fct_ptr_barrier_reseter
  82. {
  83. unsigned int size_;
  84. void(*fct_)();
  85. void_fct_ptr_barrier_reseter(unsigned int size, void(*funct)()) :
  86. size_(size), fct_(funct)
  87. {
  88. }
  89. BOOST_THREAD_MOVABLE(void_fct_ptr_barrier_reseter)
  90. //BOOST_THREAD_COPYABLE_AND_MOVABLE(void_fct_ptr_barrier_reseter)
  91. void_fct_ptr_barrier_reseter(void_fct_ptr_barrier_reseter const& other) BOOST_NOEXCEPT :
  92. size_(other.size_), fct_(other.fct_)
  93. {
  94. }
  95. void_fct_ptr_barrier_reseter(BOOST_THREAD_RV_REF(void_fct_ptr_barrier_reseter) other) BOOST_NOEXCEPT :
  96. size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
  97. {
  98. }
  99. unsigned int operator()()
  100. {
  101. fct_();
  102. return size_;
  103. }
  104. };
  105. }
  106. //BOOST_THREAD_DCL_MOVABLE(thread_detail::default_barrier_reseter)
  107. //BOOST_THREAD_DCL_MOVABLE(thread_detail::void_functor_barrier_reseter)
  108. //BOOST_THREAD_DCL_MOVABLE(thread_detail::void_fct_ptr_barrier_reseter)
  109. class barrier
  110. {
  111. static inline unsigned int check_counter(unsigned int count)
  112. {
  113. if (count == 0) boost::throw_exception(
  114. thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
  115. return count;
  116. }
  117. struct dummy
  118. {
  119. };
  120. public:
  121. BOOST_THREAD_NO_COPYABLE( barrier)
  122. explicit barrier(unsigned int count) :
  123. m_count(check_counter(count)), m_generation(0), fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))
  124. {
  125. }
  126. template <typename F>
  127. barrier(
  128. unsigned int count,
  129. BOOST_THREAD_RV_REF(F) funct,
  130. typename enable_if<
  131. typename is_void<typename result_of<F()>::type>::type, dummy*
  132. >::type=0
  133. )
  134. : m_count(check_counter(count)),
  135. m_generation(0),
  136. fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count,
  137. boost::move(funct)))
  138. )
  139. {
  140. }
  141. template <typename F>
  142. barrier(
  143. unsigned int count,
  144. F &funct,
  145. typename enable_if<
  146. typename is_void<typename result_of<F()>::type>::type, dummy*
  147. >::type=0
  148. )
  149. : m_count(check_counter(count)),
  150. m_generation(0),
  151. fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count,
  152. funct))
  153. )
  154. {
  155. }
  156. template <typename F>
  157. barrier(
  158. unsigned int count,
  159. BOOST_THREAD_RV_REF(F) funct,
  160. typename enable_if<
  161. typename is_same<typename result_of<F()>::type, unsigned int>::type, dummy*
  162. >::type=0
  163. )
  164. : m_count(check_counter(count)),
  165. m_generation(0),
  166. fct_(boost::move(funct))
  167. {
  168. }
  169. template <typename F>
  170. barrier(
  171. unsigned int count,
  172. F& funct,
  173. typename enable_if<
  174. typename is_same<typename result_of<F()>::type, unsigned int>::type, dummy*
  175. >::type=0
  176. )
  177. : m_count(check_counter(count)),
  178. m_generation(0),
  179. fct_(funct)
  180. {
  181. }
  182. barrier(unsigned int count, void(*funct)()) :
  183. m_count(check_counter(count)), m_generation(0),
  184. fct_(funct
  185. ? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_fct_ptr_barrier_reseter(count, funct))))
  186. : BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))))
  187. )
  188. {
  189. }
  190. barrier(unsigned int count, unsigned int(*funct)()) :
  191. m_count(check_counter(count)), m_generation(0),
  192. fct_(funct
  193. ? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(funct))
  194. : BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))))
  195. )
  196. {
  197. }
  198. bool wait()
  199. {
  200. boost::unique_lock < boost::mutex > lock(m_mutex);
  201. unsigned int gen = m_generation;
  202. if (--m_count == 0)
  203. {
  204. m_generation++;
  205. m_count = static_cast<unsigned int>(fct_());
  206. BOOST_ASSERT(m_count != 0);
  207. lock.unlock();
  208. m_cond.notify_all();
  209. return true;
  210. }
  211. while (gen == m_generation)
  212. m_cond.wait(lock);
  213. return false;
  214. }
  215. void count_down_and_wait()
  216. {
  217. wait();
  218. }
  219. private:
  220. mutex m_mutex;
  221. condition_variable m_cond;
  222. unsigned int m_count;
  223. unsigned int m_generation;
  224. thread_detail::size_completion_function fct_;
  225. };
  226. } // namespace boost
  227. #include <boost/config/abi_suffix.hpp>
  228. #endif