[IRBuilder] Refactor FMF interface (#121657)
[llvm-project.git] / libcxx / include / latch
blob471ef143e8d5a120507b0a501e1667adc8fffcc0
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP_LATCH
11 #define _LIBCPP_LATCH
14     latch synopsis
16 namespace std
19   class latch                                     // since C++20
20   {
21   public:
22     static constexpr ptrdiff_t max() noexcept;
24     constexpr explicit latch(ptrdiff_t __expected);
25     ~latch();
27     latch(const latch&) = delete;
28     latch& operator=(const latch&) = delete;
30     void count_down(ptrdiff_t __update = 1);
31     bool try_wait() const noexcept;
32     void wait() const;
33     void arrive_and_wait(ptrdiff_t __update = 1);
35   private:
36     ptrdiff_t __counter; // exposition only
37   };
43 #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
44 #  include <__cxx03/latch>
45 #else
46 #  include <__config>
48 #  if _LIBCPP_HAS_THREADS
50 #    include <__assert>
51 #    include <__atomic/atomic.h>
52 #    include <__atomic/atomic_sync.h>
53 #    include <__atomic/memory_order.h>
54 #    include <__cstddef/ptrdiff_t.h>
55 #    include <limits>
56 #    include <version>
58 #    if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
59 #      pragma GCC system_header
60 #    endif
62 _LIBCPP_PUSH_MACROS
63 #    include <__undef_macros>
65 #    if _LIBCPP_STD_VER >= 20
67 _LIBCPP_BEGIN_NAMESPACE_STD
69 class latch {
70   atomic<ptrdiff_t> __a_;
72 public:
73   static _LIBCPP_HIDE_FROM_ABI constexpr ptrdiff_t max() noexcept { return numeric_limits<ptrdiff_t>::max(); }
75   inline _LIBCPP_HIDE_FROM_ABI constexpr explicit latch(ptrdiff_t __expected) : __a_(__expected) {
76     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
77         __expected >= 0,
78         "latch::latch(ptrdiff_t): latch cannot be "
79         "initialized with a negative value");
80     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
81         __expected <= max(),
82         "latch::latch(ptrdiff_t): latch cannot be "
83         "initialized with a value greater than max()");
84   }
86   _LIBCPP_HIDE_FROM_ABI ~latch() = default;
87   latch(const latch&)            = delete;
88   latch& operator=(const latch&) = delete;
90   inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void count_down(ptrdiff_t __update = 1) {
91     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__update >= 0, "latch::count_down called with a negative value");
92     auto const __old = __a_.fetch_sub(__update, memory_order_release);
93     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
94         __update <= __old,
95         "latch::count_down called with a value greater "
96         "than the internal counter");
97     if (__old == __update)
98       __a_.notify_all();
99   }
100   inline _LIBCPP_HIDE_FROM_ABI bool try_wait() const noexcept {
101     auto __value = __a_.load(memory_order_acquire);
102     return try_wait_impl(__value);
103   }
104   inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait() const {
105     std::__atomic_wait_unless(__a_, memory_order_acquire, [this](ptrdiff_t& __value) -> bool {
106       return try_wait_impl(__value);
107     });
108   }
109   inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void arrive_and_wait(ptrdiff_t __update = 1) {
110     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__update >= 0, "latch::arrive_and_wait called with a negative value");
111     // other preconditions on __update are checked in count_down()
113     count_down(__update);
114     wait();
115   }
117 private:
118   _LIBCPP_HIDE_FROM_ABI bool try_wait_impl(ptrdiff_t& __value) const noexcept { return __value == 0; }
121 _LIBCPP_END_NAMESPACE_STD
123 #    endif // _LIBCPP_STD_VER >= 20
125 _LIBCPP_POP_MACROS
127 #  endif // _LIBCPP_HAS_THREADS
129 #  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
130 #    include <atomic>
131 #    include <cstddef>
132 #  endif
133 #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
135 #endif // _LIBCPP_LATCH