File indexing completed on 2025-01-18 09:29:53
0001 #ifndef BOOST_COMPAT_LATCH_HPP_INCLUDED
0002 #define BOOST_COMPAT_LATCH_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009 #include <boost/assert.hpp>
0010
0011 #include <climits>
0012 #include <condition_variable>
0013 #include <mutex>
0014
0015 namespace boost
0016 {
0017 namespace compat
0018 {
0019
0020 class latch {
0021 private:
0022 std::ptrdiff_t n_;
0023 mutable std::mutex m_;
0024 mutable std::condition_variable cv_;
0025
0026 public:
0027 explicit latch(std::ptrdiff_t expected) : n_{expected}, m_{}, cv_{} {
0028 BOOST_ASSERT(n_ >= 0);
0029 BOOST_ASSERT(n_ <= max());
0030 }
0031
0032 latch(latch const &) = delete;
0033 latch &operator=(latch const &) = delete;
0034
0035 ~latch() = default;
0036
0037 void count_down(std::ptrdiff_t n = 1) {
0038 std::unique_lock<std::mutex> lk(m_);
0039 count_down_and_notify(lk, n);
0040 }
0041
0042 bool try_wait() const noexcept {
0043 std::unique_lock<std::mutex> lk(m_);
0044 return is_ready();
0045 }
0046
0047 void wait() const {
0048 std::unique_lock<std::mutex> lk(m_);
0049 wait_impl(lk);
0050 }
0051
0052 void arrive_and_wait(std::ptrdiff_t n = 1) {
0053 std::unique_lock<std::mutex> lk(m_);
0054 bool should_wait = count_down_and_notify(lk, n);
0055 if (should_wait) {
0056 wait_impl(lk);
0057 }
0058 }
0059
0060 static constexpr std::ptrdiff_t max() noexcept { return PTRDIFF_MAX; }
0061
0062 private:
0063 bool is_ready() const { return n_ == 0; }
0064
0065 bool count_down_and_notify(std::unique_lock<std::mutex> &lk,
0066 std::ptrdiff_t n) {
0067 BOOST_ASSERT(n <= n_);
0068 n_ -= n;
0069 if (n_ == 0) {
0070 lk.unlock();
0071 cv_.notify_all();
0072 return false;
0073 }
0074
0075 return true;
0076 }
0077
0078 void wait_impl(std::unique_lock<std::mutex> &lk) const {
0079 cv_.wait(lk, [this] { return this->is_ready(); });
0080 }
0081 };
0082
0083 }
0084 }
0085
0086 #endif