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