Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/thread/completion_latch.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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 2013 Vicente J. Botet Escriba | |
5 | |
6 #ifndef BOOST_THREAD_COMPLETION_LATCH_HPP | |
7 #define BOOST_THREAD_COMPLETION_LATCH_HPP | |
8 | |
9 #include <boost/thread/detail/config.hpp> | |
10 #include <boost/thread/detail/delete.hpp> | |
11 #include <boost/thread/detail/counter.hpp> | |
12 | |
13 #include <boost/thread/mutex.hpp> | |
14 #include <boost/thread/lock_types.hpp> | |
15 #include <boost/thread/condition_variable.hpp> | |
16 #include <boost/chrono/duration.hpp> | |
17 #include <boost/chrono/time_point.hpp> | |
18 #include <boost/assert.hpp> | |
19 #ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL | |
20 #include <boost/function.hpp> | |
21 #else | |
22 #include <functional> | |
23 #endif | |
24 //#include <boost/thread/latch.hpp> | |
25 | |
26 #include <boost/config/abi_prefix.hpp> | |
27 | |
28 namespace boost | |
29 { | |
30 namespace thread_detail | |
31 { | |
32 void noop() | |
33 { | |
34 } | |
35 } | |
36 class completion_latch | |
37 { | |
38 public: | |
39 /// the implementation defined completion function type | |
40 #ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL | |
41 typedef function<void()> completion_function; | |
42 #else | |
43 typedef std::function<void()> completion_function; | |
44 #endif | |
45 /// noop completion function factory | |
46 static completion_function noop() | |
47 { | |
48 return completion_function(&thread_detail::noop); | |
49 } | |
50 | |
51 private: | |
52 struct around_wait; | |
53 friend struct around_wait; | |
54 struct around_wait | |
55 { | |
56 completion_latch &that_; | |
57 boost::unique_lock<boost::mutex> &lk_; | |
58 around_wait(completion_latch &that, boost::unique_lock<boost::mutex> &lk) | |
59 : that_(that), lk_(lk) | |
60 { | |
61 that_.leavers_.cond_.wait(lk, detail::counter_is_zero(that_.leavers_)); | |
62 that_.waiters_.inc_and_notify_all(); | |
63 that_.leavers_.cond_.wait(lk, detail::counter_is_not_zero(that_.leavers_)); | |
64 } | |
65 ~around_wait() | |
66 { | |
67 that_.waiters_.dec_and_notify_all(); | |
68 } | |
69 }; | |
70 | |
71 bool count_down(unique_lock<mutex> &lk) | |
72 { | |
73 BOOST_ASSERT(count_ > 0); | |
74 if (--count_ == 0) | |
75 { | |
76 waiters_.cond_.wait(lk, detail::counter_is_not_zero(waiters_)); | |
77 leavers_.assign_and_notify_all(waiters_); | |
78 count_.cond_.notify_all(); | |
79 waiters_.cond_.wait(lk, detail::counter_is_zero(waiters_)); | |
80 leavers_.assign_and_notify_all(0); | |
81 lk.unlock(); | |
82 funct_(); | |
83 return true; | |
84 } | |
85 return false; | |
86 } | |
87 | |
88 public: | |
89 BOOST_THREAD_NO_COPYABLE( completion_latch ) | |
90 | |
91 /// Constructs a latch with a given count. | |
92 completion_latch(std::size_t count) : | |
93 count_(count), funct_(noop()), waiters_(0), leavers_(0) | |
94 { | |
95 } | |
96 | |
97 /// Constructs a latch with a given count and a completion function. | |
98 template <typename F> | |
99 completion_latch(std::size_t count, BOOST_THREAD_RV_REF(F) funct) : | |
100 count_(count), | |
101 funct_(boost::move(funct)), | |
102 waiters_(0), | |
103 leavers_(0) | |
104 { | |
105 } | |
106 template <typename F> | |
107 completion_latch(std::size_t count, void(*funct)()) : | |
108 count_(count), funct_(funct), waiters_(0), leavers_(0) | |
109 { | |
110 } | |
111 | |
112 /// | |
113 ~completion_latch() | |
114 { | |
115 } | |
116 | |
117 /// Blocks until the latch has counted down to zero. | |
118 void wait() | |
119 { | |
120 boost::unique_lock<boost::mutex> lk(mutex_); | |
121 around_wait aw(*this, lk); | |
122 count_.cond_.wait(lk, detail::counter_is_zero(count_)); | |
123 } | |
124 | |
125 /// @return true if the internal counter is already 0, false otherwise | |
126 bool try_wait() | |
127 { | |
128 boost::unique_lock<boost::mutex> lk(mutex_); | |
129 around_wait aw(*this, lk); | |
130 return (count_ == 0); | |
131 } | |
132 | |
133 /// try to wait for a specified amount of time | |
134 /// @return whether there is a timeout or not. | |
135 template <class Rep, class Period> | |
136 cv_status wait_for(const chrono::duration<Rep, Period>& rel_time) | |
137 { | |
138 boost::unique_lock<boost::mutex> lk(mutex_); | |
139 around_wait aw(*this, lk); | |
140 return count_.cond_.wait_for(lk, rel_time, detail::counter_is_zero(count_)) | |
141 ? cv_status::no_timeout | |
142 : cv_status::timeout; | |
143 } | |
144 | |
145 /// try to wait until the specified time_point is reached | |
146 /// @return whether there is a timeout or not. | |
147 template <class Clock, class Duration> | |
148 cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) | |
149 { | |
150 boost::unique_lock<boost::mutex> lk(mutex_); | |
151 around_wait aw(*this, lk); | |
152 return count_.cond_.wait_until(lk, abs_time, detail::counter_is_zero(count_)) | |
153 ? cv_status::no_timeout | |
154 : cv_status::timeout; | |
155 } | |
156 | |
157 /// Decrement the count and notify anyone waiting if we reach zero. | |
158 /// @Requires count must be greater than 0 | |
159 void count_down() | |
160 { | |
161 unique_lock<mutex> lk(mutex_); | |
162 count_down(lk); | |
163 } | |
164 void signal() | |
165 { | |
166 count_down(); | |
167 } | |
168 | |
169 /// Decrement the count and notify anyone waiting if we reach zero. | |
170 /// Blocks until the latch has counted down to zero. | |
171 /// @Requires count must be greater than 0 | |
172 void count_down_and_wait() | |
173 { | |
174 boost::unique_lock<boost::mutex> lk(mutex_); | |
175 if (count_down(lk)) | |
176 { | |
177 return; | |
178 } | |
179 around_wait aw(*this, lk); | |
180 count_.cond_.wait(lk, detail::counter_is_zero(count_)); | |
181 } | |
182 void sync() | |
183 { | |
184 count_down_and_wait(); | |
185 } | |
186 | |
187 /// Reset the counter | |
188 /// #Requires This method may only be invoked when there are no other threads currently inside the count_down_and_wait() method. | |
189 void reset(std::size_t count) | |
190 { | |
191 boost::lock_guard<boost::mutex> lk(mutex_); | |
192 //BOOST_ASSERT(count_ == 0); | |
193 count_ = count; | |
194 } | |
195 | |
196 /// Resets the latch with the new completion function. | |
197 /// The next time the internal count reaches 0, this function will be invoked. | |
198 /// This completion function may only be invoked when there are no other threads | |
199 /// currently inside the count_down and wait related functions. | |
200 /// It may also be invoked from within the registered completion function. | |
201 /// @Returns the old completion function if any or noop if | |
202 | |
203 #ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL | |
204 template <typename F> | |
205 completion_function then(BOOST_THREAD_RV_REF(F) funct) | |
206 { | |
207 boost::lock_guard<boost::mutex> lk(mutex_); | |
208 completion_function tmp(funct_); | |
209 funct_ = boost::move(funct); | |
210 return tmp; | |
211 } | |
212 #endif | |
213 completion_function then(void(*funct)()) | |
214 { | |
215 boost::lock_guard<boost::mutex> lk(mutex_); | |
216 completion_function tmp(funct_); | |
217 funct_ = completion_function(funct); | |
218 return tmp; | |
219 } | |
220 | |
221 private: | |
222 mutex mutex_; | |
223 detail::counter count_; | |
224 completion_function funct_; | |
225 detail::counter waiters_; | |
226 detail::counter leavers_; | |
227 }; | |
228 | |
229 } // namespace boost | |
230 | |
231 #include <boost/config/abi_suffix.hpp> | |
232 | |
233 #endif |