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