annotate DEPENDENCIES/generic/include/boost/thread/completion_latch.hpp @ 133:4acb5d8d80b6 tip

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