NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
barrier.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_ASYNC_BARRIER_HPP__
2#define NEFORCE_CORE_ASYNC_BARRIER_HPP__
3
11
15NEFORCE_BEGIN_NAMESPACE__
16
22
28
36 NEFORCE_ALWAYS_INLINE void operator()() noexcept {}
37};
38
39
48template <typename CmplFunc>
50 using phase_ref_t = atomic_ref_base<byte_t>;
51 using phase_cref_t = atomic_ref_base<const byte_t>;
52
53 static constexpr auto phase_alignment = phase_ref_t::required_alignment;
54
61 struct alignas(64) state_data {
62 alignas(phase_alignment) array<byte_t, 64> tickets;
63 };
64
65 ptrdiff_t expected_count_;
66 unique_ptr<state_data[]> state_array_;
67 atomic_base<ptrdiff_t> expected_adjustment_;
68 CmplFunc completion_function_;
69 alignas(phase_alignment) byte_t current_phase_;
70
79 bool do_arrive(const byte_t old_phase, size_t current_index) {
80 const auto old_phase_value = old_phase;
81 const auto half_step = static_cast<byte_t>(old_phase_value + 1);
82 const auto full_step = static_cast<byte_t>(old_phase_value + 2);
83
84 size_t current_expected = expected_count_;
85 current_index %= ((expected_count_ + 1) >> 1);
86
87 for (int round = 0;; ++round) {
88 if (current_expected <= 1) {
89 return true;
90 }
91
92 size_t const end_node = ((current_expected + 1) >> 1), last_node = end_node - 1;
93
94 for (;; ++current_index) {
95 if (current_index == end_node) {
96 current_index = 0;
97 }
98
99 auto expected_phase = old_phase;
100 phase_ref_t phase_ref(state_array_[current_index].tickets[round]);
101
102 if (current_index == last_node && (current_expected & 1)) {
103 if (phase_ref.compare_exchange_strong(expected_phase, full_step, memory_order_acq_rel)) {
104 break;
105 }
106 } else if (phase_ref.compare_exchange_strong(expected_phase, half_step, memory_order_acq_rel)) {
107 return false;
108 } else if (expected_phase == half_step) {
109 if (phase_ref.compare_exchange_strong(expected_phase, full_step, memory_order_acq_rel)) {
110 break;
111 }
112 }
113 }
114
115 current_expected = last_node + 1;
116 current_index >>= 1;
117 }
118 }
119
120public:
122
127 static constexpr ptrdiff_t max() noexcept { return numeric_traits<ptrdiff_t>::max(); }
128
134 tree_barrier(const ptrdiff_t expected, CmplFunc completion) :
135 expected_count_(expected),
136 expected_adjustment_(0),
137 completion_function_(_NEFORCE 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 NEFORCE_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 = [=] { return phase_ref.load(memory_order_acquire) != old_phase; };
180 _NEFORCE atomic_wait_address(&current_phase_, test_function);
181 }
182
189 expected_adjustment_.fetch_sub(1, memory_order_relaxed);
190 ignore = arrive(1);
191 }
192};
193
194
203template <typename CmplFunc = empty_completion>
204class barrier {
205 using algorithm_type = tree_barrier<CmplFunc>;
206 algorithm_type barrier_impl_;
207
208public:
216 class arrival_token final {
217 public:
220 ~arrival_token() = default;
221
222 private:
223 friend class barrier;
224 using internal_token = typename algorithm_type::arrival_token;
225 explicit arrival_token(internal_token token) noexcept :
226 token_(token) {}
227 internal_token token_;
228 };
229
234 static constexpr ptrdiff_t max() noexcept { return algorithm_type::max(); }
235
241 explicit barrier(ptrdiff_t count, CmplFunc completion = CmplFunc()) :
242 barrier_impl_(count, _NEFORCE move(completion)) {}
243
244 barrier(barrier const&) = delete;
245 barrier& operator=(barrier const&) = delete;
246
252 NEFORCE_NODISCARD arrival_token arrive(ptrdiff_t update = 1) { return arrival_token{barrier_impl_.arrive(update)}; }
253
258 void wait(arrival_token&& phase) const { barrier_impl_.wait(_NEFORCE move(phase.token_)); }
259
265 void arrive_and_wait() { this->wait(arrive()); }
266
272 void arrive_and_drop() { barrier_impl_.arrive_and_drop(); }
273};
274 // ThreadSync
276 // AsyncComponents
278
279NEFORCE_END_NAMESPACE__
280#endif // NEFORCE_CORE_ASYNC_BARRIER_HPP__
固定大小数组容器
原子操作基本工具
固定大小数组容器
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()
到达并等待
static constexpr ptrdiff_t max() noexcept
获取最大线程数
NEFORCE_NODISCARD arrival_token arrive(ptrdiff_t update=1)
到达屏障点
barrier(ptrdiff_t count, CmplFunc completion=CmplFunc())
构造函数
static NEFORCE_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
到达令牌类型
NEFORCE_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)
统计范围内等于指定值的元素数量
NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t round(const decimal_t x) noexcept
四舍五入
NEFORCE_INLINE17 constexpr auto memory_order_acq_rel
获取-释放内存顺序常量
NEFORCE_INLINE17 constexpr auto memory_order_release
释放内存顺序常量
NEFORCE_INLINE17 constexpr auto memory_order_relaxed
宽松内存顺序常量
NEFORCE_INLINE17 constexpr auto memory_order_acquire
获取内存顺序常量
int64_t ptrdiff_t
指针差类型
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
NEFORCE_CONSTEXPR20 unique_ptr< T > make_unique(Args &&... args)
创建unique_ptr
原子类型基础模板类
原子引用基础模板类
空完成函数
哈希函数的主模板
线程管理类