barrier.hpp 5.1 KB

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