llvm-project

Форк
0
129 строк · 3.7 Кб
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
//===----------------------------------------------------------------------===//
9

10
#ifndef _LIBCPP_LATCH
11
#define _LIBCPP_LATCH
12

13
/*
14
    latch synopsis
15

16
namespace std
17
{
18

19
  class latch
20
  {
21
  public:
22
    static constexpr ptrdiff_t max() noexcept;
23

24
    constexpr explicit latch(ptrdiff_t __expected);
25
    ~latch();
26

27
    latch(const latch&) = delete;
28
    latch& operator=(const latch&) = delete;
29

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);
34

35
  private:
36
    ptrdiff_t __counter; // exposition only
37
  };
38

39
}
40

41
*/
42

43
#include <__config>
44

45
#ifdef _LIBCPP_HAS_NO_THREADS
46
#  error "<latch> is not supported since libc++ has been configured without support for threads."
47
#endif
48

49
#include <__assert>
50
#include <__atomic/atomic_base.h>
51
#include <__atomic/atomic_sync.h>
52
#include <__atomic/memory_order.h>
53
#include <cstddef>
54
#include <limits>
55
#include <version>
56

57
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
58
#  pragma GCC system_header
59
#endif
60

61
_LIBCPP_PUSH_MACROS
62
#include <__undef_macros>
63

64
#if _LIBCPP_STD_VER >= 14
65

66
_LIBCPP_BEGIN_NAMESPACE_STD
67

68
class _LIBCPP_DEPRECATED_ATOMIC_SYNC latch {
69
  __atomic_base<ptrdiff_t> __a_;
70

71
public:
72
  static _LIBCPP_HIDE_FROM_ABI constexpr ptrdiff_t max() noexcept { return numeric_limits<ptrdiff_t>::max(); }
73

74
  inline _LIBCPP_HIDE_FROM_ABI constexpr explicit latch(ptrdiff_t __expected) : __a_(__expected) {
75
    _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
76
        __expected >= 0,
77
        "latch::latch(ptrdiff_t): latch cannot be "
78
        "initialized with a negative value");
79
    _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
80
        __expected <= max(),
81
        "latch::latch(ptrdiff_t): latch cannot be "
82
        "initialized with a value greater than max()");
83
  }
84

85
  _LIBCPP_HIDE_FROM_ABI ~latch() = default;
86
  latch(const latch&)            = delete;
87
  latch& operator=(const latch&) = delete;
88

89
  inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void count_down(ptrdiff_t __update = 1) {
90
    _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__update >= 0, "latch::count_down called with a negative value");
91
    auto const __old = __a_.fetch_sub(__update, memory_order_release);
92
    _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
93
        __update <= __old,
94
        "latch::count_down called with a value greater "
95
        "than the internal counter");
96
    if (__old == __update)
97
      __a_.notify_all();
98
  }
99
  inline _LIBCPP_HIDE_FROM_ABI bool try_wait() const noexcept {
100
    auto __value = __a_.load(memory_order_acquire);
101
    return try_wait_impl(__value);
102
  }
103
  inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait() const {
104
    std::__atomic_wait_unless(
105
        __a_, [this](ptrdiff_t& __value) -> bool { return try_wait_impl(__value); }, memory_order_acquire);
106
  }
107
  inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void arrive_and_wait(ptrdiff_t __update = 1) {
108
    _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__update >= 0, "latch::arrive_and_wait called with a negative value");
109
    // other preconditions on __update are checked in count_down()
110

111
    count_down(__update);
112
    wait();
113
  }
114

115
private:
116
  _LIBCPP_HIDE_FROM_ABI bool try_wait_impl(ptrdiff_t& __value) const noexcept { return __value == 0; }
117
};
118

119
_LIBCPP_END_NAMESPACE_STD
120

121
#endif // _LIBCPP_STD_VER >= 14
122

123
_LIBCPP_POP_MACROS
124

125
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
126
#  include <atomic>
127
#endif
128

129
#endif //_LIBCPP_LATCH
130

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.