SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
latch.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <atomic>
16 #include <cassert>
17 #include <seqan3/std/new>
18 
20 
21 namespace seqan3::detail
22 {
23 
38 class latch
39 {
40 public:
45  latch() = delete;
46  latch(latch const &) = delete;
47  latch(latch &&) = delete;
48  latch & operator=(latch const &) = delete;
49  latch & operator=(latch &&) = delete;
50 
52  ~latch()
53  {
54  spin_delay delay{};
55  while (num_waiting.load(std::memory_order_acquire) > 0)
56  delay.wait();
57  }
58 
62  explicit latch(ptrdiff_t const expected) : counter{expected}
63  {
64  assert(expected >= 0);
65  num_waiting.store(0, std::memory_order_relaxed);
66  }
68 
85  void arrive(ptrdiff_t n = 1) noexcept
86  {
87  assert(counter.load(std::memory_order_acquire) >= n);
88  assert(counter.load(std::memory_order_acquire) >= 0);
89 
90  counter.fetch_sub(n, std::memory_order_acq_rel);
91  }
92 
110  void arrive_and_wait(ptrdiff_t n = 1) noexcept
111  {
112  ++num_waiting; // ensure that destructor is not finished in-between the arrive and wait call.
113  arrive(n);
114  wait();
115  --num_waiting;
116  }
117 
128  bool try_wait() const noexcept
129  {
130  return counter.load(std::memory_order_acquire) == 0;
131  }
132 
148  void wait() const
149  {
150  ++num_waiting; // register waiting thread to synchronise with destructor.
151  spin_delay delay{};
152  while (counter.load(std::memory_order_acquire) > 0)
153  delay.wait();
154  --num_waiting;
155  }
156 
157 private:
162 };
163 
164 } // namespace seqan3::detail
constexpr std::size_t hardware_destructive_interference_size
Minimum offset between two objects to avoid false sharing.
Definition: new:34
The <new> header from C++17's standard library.
Provides seqan3::detail::spin_delay.