[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / libcxx / include / latch
blobad7b35579913b30a298eece58094db879a48665d
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
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 #include <__config>
45 #ifdef _LIBCPP_HAS_NO_THREADS
46 #  error "<latch> is not supported since libc++ has been configured without support for threads."
47 #endif
49 #include <__assert> // all public C++ headers provide the assertion handler
50 #include <__atomic/atomic_base.h>
51 #include <__atomic/atomic_sync.h>
52 #include <__atomic/memory_order.h>
53 #include <__availability>
54 #include <cstddef>
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 >= 14
67 _LIBCPP_BEGIN_NAMESPACE_STD
69 class latch {
70   __atomic_base<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 { return 0 == __a_.load(memory_order_acquire); }
101   inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait() const {
102     __cxx_atomic_wait(&__a_.__a_, [this]() -> bool { return try_wait(); });
103   }
104   inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void arrive_and_wait(ptrdiff_t __update = 1) {
105     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__update >= 0, "latch::arrive_and_wait called with a negative value");
106     // other preconditions on __update are checked in count_down()
108     count_down(__update);
109     wait();
110   }
113 _LIBCPP_END_NAMESPACE_STD
115 #endif // _LIBCPP_STD_VER >= 14
117 _LIBCPP_POP_MACROS
119 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
120 #  include <atomic>
121 #endif
123 #endif //_LIBCPP_LATCH