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