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