SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
latch.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2021, 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:
41 
46  latch() = delete;
47  latch(latch const &) = delete;
48  latch(latch &&) = delete;
49  latch & operator=(latch const &) = delete;
50  latch & operator=(latch &&) = delete;
51 
53  ~latch()
54  {
55  spin_delay delay{};
56  while (num_waiting.load(std::memory_order_acquire) > 0)
57  delay.wait();
58  }
59 
63  explicit latch(ptrdiff_t const expected) :
64  counter{expected}
65  {
66  assert(expected >= 0);
67  num_waiting.store(0, std::memory_order_relaxed);
68  }
70 
87  void arrive(ptrdiff_t n = 1) noexcept
88  {
89  assert(counter.load(std::memory_order_acquire) >= n);
90  assert(counter.load(std::memory_order_acquire) >= 0);
91 
92  counter.fetch_sub(n, std::memory_order_acq_rel);
93  }
94 
112  void arrive_and_wait(ptrdiff_t n = 1) noexcept
113  {
114  ++num_waiting; // ensure that destructor is not finished in-between the arrive and wait call.
115  arrive(n);
116  wait();
117  --num_waiting;
118  }
119 
130  bool try_wait() const noexcept
131  {
132  return counter.load(std::memory_order_acquire) == 0;
133  }
134 
150  void wait() const
151  {
152  ++num_waiting; // register waiting thread to synchronise with destructor.
153  spin_delay delay{};
154  while (counter.load(std::memory_order_acquire) > 0)
155  delay.wait();
156  --num_waiting;
157  }
158 
159 private:
160 
165 };
166 
167 } // namespace seqan3::detail
constexpr std::size_t hardware_destructive_interference_size
Minimum offset between two objects to avoid false sharing.
Definition: new:34
Provides C++17/20 additions to the <new> header, if they are not already available.
Provides seqan3::detail::spin_delay.