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