MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
barrier.hpp
浏览该文件的文档.
1#ifndef MSTL_CORE_ASYNC_BARRIER_HPP__
2#define MSTL_CORE_ASYNC_BARRIER_HPP__
3
11
13#include "MSTL/core/container/array.hpp"
17
23
31 MSTL_ALWAYS_INLINE void operator ()() noexcept {}
32};
33
34
43template <typename CmplFunc>
45 using phase_ref_t = atomic_ref_base<byte_t>;
46 using phase_cref_t = atomic_ref_base<const byte_t>;
47
48 static constexpr auto phase_alignment = phase_ref_t::required_alignment;
49
56 struct alignas(64) state_data {
57 alignas(phase_alignment) array<byte_t, 64> tickets;
58 };
59
60 ptrdiff_t expected_count_;
61 unique_ptr<state_data[]> state_array_;
62 atomic_base<ptrdiff_t> expected_adjustment_;
63 CmplFunc completion_function_;
64 alignas(phase_alignment) byte_t current_phase_;
65
74 bool do_arrive(const byte_t old_phase, size_t current_index) {
75 const auto old_phase_value = old_phase;
76 const auto half_step = static_cast<byte_t>(old_phase_value + 1);
77 const auto full_step = static_cast<byte_t>(old_phase_value + 2);
78
79 size_t current_expected = expected_count_;
80 current_index %= ((expected_count_ + 1) >> 1);
81
82 for (int round = 0; ; ++round) {
83 if (current_expected <= 1)
84 return true;
85
86 size_t const end_node =
87 ((current_expected + 1) >> 1),
88 last_node = end_node - 1;
89
90 for ( ; ; ++current_index) {
91 if (current_index == end_node)
92 current_index = 0;
93
94 auto expected_phase = old_phase;
95 phase_ref_t phase_ref(state_array_[current_index].tickets[round]);
96
97 if (current_index == last_node && (current_expected & 1)) {
98 if (phase_ref.compare_exchange_strong(
99 expected_phase, full_step, memory_order_acq_rel)) {
100 break;
101 }
102 } else if (phase_ref.compare_exchange_strong(
103 expected_phase, half_step, memory_order_acq_rel)) {
104 return false;
105 } else if (expected_phase == half_step) {
106 if (phase_ref.compare_exchange_strong(
107 expected_phase, full_step, memory_order_acq_rel)) {
108 break;
109 }
110 }
111 }
112
113 current_expected = last_node + 1;
114 current_index >>= 1;
115 }
116 }
117
118public:
120
125 static constexpr ptrdiff_t max() noexcept {
127 }
128
134 tree_barrier(const ptrdiff_t expected, CmplFunc completion)
135 : expected_count_(expected),
136 expected_adjustment_(0),
137 completion_function_(_MSTL move(completion)),
138 current_phase_(static_cast<byte_t>(0)) {
139 size_t const count = (expected_count_ + 1) >> 1;
140 state_array_ = make_unique<state_data[]>(count);
141 }
142
151 MSTL_NODISCARD arrival_token arrive(ptrdiff_t update) {
152 constexpr hash<thread::id> hasher;
153 const size_t current_index = hasher(this_thread::id());
154 phase_ref_t phase_ref(current_phase_);
155 const auto old_phase = phase_ref.load(memory_order_relaxed);
156 const auto current_phase_value = static_cast<byte_t>(old_phase);
157
158 for(; update; --update) {
159 if(do_arrive(old_phase, current_index)) {
160 completion_function_();
161 expected_count_ += expected_adjustment_.load(memory_order_relaxed);
162 expected_adjustment_.store(0, memory_order_relaxed);
163 const auto new_phase = static_cast<byte_t>(current_phase_value + 2);
164 phase_ref.store(new_phase, memory_order_release);
165 phase_ref.notify_all();
166 }
167 }
168 return old_phase;
169 }
170
177 void wait(arrival_token&& old_phase) const {
178 phase_cref_t phase_ref(current_phase_);
179 auto const test_function = [=] {
180 return phase_ref.load(memory_order_acquire) != old_phase;
181 };
182 _MSTL atomic_wait_address(&current_phase_, test_function);
183 }
184
191 expected_adjustment_.fetch_sub(1, memory_order_relaxed);
192 static_cast<void>(arrive(1));
193 }
194};
195
196
205template <typename CmplFunc = empty_completion>
206class barrier {
207 using algorithm_type = tree_barrier<CmplFunc>;
208 algorithm_type barrier_impl_;
209
210public:
218 class arrival_token final {
219 public:
222 ~arrival_token() = default;
223
224 private:
225 friend class barrier;
226 using internal_token = typename algorithm_type::arrival_token;
227 explicit arrival_token(internal_token token) noexcept : token_(token) { }
228 internal_token token_;
229 };
230
235 static constexpr ptrdiff_t max() noexcept {
236 return algorithm_type::max();
237 }
238
244 explicit barrier(ptrdiff_t count, CmplFunc completion = CmplFunc())
245 : barrier_impl_(count, _MSTL move(completion)) { }
246
247 barrier(barrier const&) = delete;
248 barrier& operator =(barrier const&) = delete;
249
255 MSTL_NODISCARD arrival_token arrive(ptrdiff_t update = 1) {
256 return arrival_token{barrier_impl_.arrive(update)};
257 }
258
263 void wait(arrival_token&& phase) const {
264 barrier_impl_.wait(_MSTL move(phase.token_));
265 }
266
273 this->wait(arrive());
274 }
275
282 barrier_impl_.arrive_and_drop();
283 }
284};
285 // Barrier
287
289#endif // MSTL_CORE_ASYNC_BARRIER_HPP__
MSTL原子操作基本工具
arrival_token & operator=(arrival_token &&)=default
移动赋值运算符
~arrival_token()=default
析构函数
arrival_token(arrival_token &&)=default
移动构造函数
通用屏障类
void wait(arrival_token &&phase) const
等待屏障
void arrive_and_drop()
到达并退出
void arrive_and_wait()
到达并等待
MSTL_NODISCARD arrival_token arrive(ptrdiff_t update=1)
到达屏障点
static constexpr ptrdiff_t max() noexcept
获取最大线程数
barrier(ptrdiff_t count, CmplFunc completion=CmplFunc())
构造函数
static MSTL_NODISCARD constexpr T max() noexcept
获取类型的最大值
树形屏障
void wait(arrival_token &&old_phase) const
等待屏障
static constexpr ptrdiff_t max() noexcept
获取最大线程数
tree_barrier(const ptrdiff_t expected, CmplFunc completion)
构造函数
void arrive_and_drop()
到达并退出
byte_t arrival_token
到达令牌类型
MSTL_NODISCARD arrival_token arrive(ptrdiff_t update)
到达屏障点
独占智能指针
void atomic_wait_address(const T *addr, Pred pred) noexcept
基于谓词的原子等待
unsigned char byte_t
字节类型,定义为无符号字符
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 decimal_t round(const decimal_t x) noexcept
四舍五入
MSTL_INLINE17 constexpr auto memory_order_release
释放内存顺序常量
MSTL_INLINE17 constexpr auto memory_order_acq_rel
获取-释放内存顺序常量
MSTL_INLINE17 constexpr auto memory_order_relaxed
宽松内存顺序常量
MSTL_INLINE17 constexpr auto memory_order_acquire
获取内存顺序常量
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
int64_t ptrdiff_t
指针差类型
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
MSTL_CONSTEXPR20 unique_ptr< T > make_unique(Args &&... args)
创建unique_ptr
原子类型基础模板类
原子引用基础模板类
空完成函数
哈希函数的主模板
MSTL线程支持
MSTL独占智能指针