MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
atomic_wait.hpp
浏览该文件的文档.
1#ifndef MSTL_CORE_ASYNC_ATOMIC_WAIT_HPP__
2#define MSTL_CORE_ASYNC_ATOMIC_WAIT_HPP__
3
10
15
21
29 bool operator ()() const noexcept { return false; }
30};
31
46template <typename Pred, typename Spin = default_spin_policy>
47bool atomic_spin(Pred& pred, Spin spin = Spin{}) noexcept {
48 constexpr auto atomic_spin_count = 16;
49 constexpr auto atomic_spin_count_relax = 12;
50 for (auto idx = 0; idx < atomic_spin_count; ++idx) {
51 if (pred()) return true;
52 if (idx < atomic_spin_count_relax) {
53 this_thread::relax();
54 } else {
55 this_thread::yield();
56 }
57 }
58
59 while (spin()) {
60 if (pred()) return true;
61 }
62 return false;
63}
64
67
75struct waiter_pool_base {
76 static constexpr auto align_inner = 64;
77
78 alignas(align_inner) platform_wait_t wait = 0;
79 alignas(align_inner) platform_wait_t value = 0;
80
81 waiter_pool_base() = default;
82
88 void waiter_enter_wait() noexcept {
89#ifdef MSTL_PLATFORM_WINDOWS__
90 ::_InterlockedIncrement(&wait);
91#else
92 __atomic_fetch_add(&wait, 1, __ATOMIC_SEQ_CST);
93#endif
94 }
95
101 void waiter_leave_wait() noexcept {
102#ifdef MSTL_PLATFORM_WINDOWS__
103 ::_InterlockedDecrement(&wait);
104#else
105 __atomic_fetch_sub(&wait, 1, __ATOMIC_RELEASE);
106#endif
107 }
108
113 bool waiter_waiting() const noexcept {
114#ifdef MSTL_PLATFORM_WINDOWS__
115 platform_wait_t res = ::_InterlockedExchangeAdd(
116 const_cast<volatile platform_wait_t*>(&wait), 0);
117#else
118 platform_wait_t res;
119 __atomic_load(&wait, &res, __ATOMIC_SEQ_CST);
120#endif
121 return res != 0;
122 }
123
130 void waiter_notify(platform_wait_t* addr, bool all, const bool bare) const noexcept {
131 if (addr == &value) {
132#ifdef MSTL_PLATFORM_WINDOWS__
133 ::_InterlockedIncrement(addr);
134#else
135 __atomic_fetch_add(addr, 1, __ATOMIC_SEQ_CST);
136#endif
137 all = true;
138 }
139 if (bare || waiter_waiting()) {
140 _MSTL futex_notify(addr, all);
141 }
142 }
143
151 static waiter_pool_base& waiter_for(const void* addr) noexcept{
152 constexpr uintptr_t pool_size = 16;
153 static waiter_pool_base waiter[pool_size];
154 const auto key = (reinterpret_cast<uintptr_t>(addr) >> 2) % pool_size;
155 return waiter[key];
156 }
157};
158
165struct waiter_pool : waiter_pool_base {
171 MSTL_ALWAYS_INLINE void waiter_do_wait(platform_wait_t* addr, const platform_wait_t old) const noexcept {
172 _MSTL futex_wait(addr, old);
173 }
174};
175
176
184template <typename T>
185struct waiter_base {
186private:
187 template <typename U, enable_if_t<platform_wait_valid_v<U>, int> = 0>
188 MSTL_ALWAYS_INLINE static void waiter_do_spin_v_impl(
189 platform_wait_t*, const U& old, platform_wait_t& value) {
190 _MSTL memory_copy(&value, &old, sizeof(value));
191 }
192 template <typename U, enable_if_t<!platform_wait_valid_v<U>, int> = 0>
193 MSTL_ALWAYS_INLINE static void waiter_do_spin_v_impl(
194 platform_wait_t* addr, const U&, platform_wait_t& value) {
195#ifdef MSTL_PLATFORM_WINDOWS__
196 value = ::_InterlockedExchangeAdd(addr, 0);
197#else
198 __atomic_load(addr, &value, __ATOMIC_ACQUIRE);
199#endif
200 }
201
202public:
203 using waiter_type = T;
204
205 waiter_type& waiter_;
206 platform_wait_t* addr_;
207
211 template <typename U>
213 waiter_wait_addr(const U* addr, platform_wait_t*) {
214 return reinterpret_cast<platform_wait_t*>(const_cast<U*>(addr));
215 }
216
220 template <typename U>
222 waiter_wait_addr(const U*, platform_wait_t* wait) {
223 return wait;
224 }
225
229 static waiter_type& waiter_for(const void* addr) noexcept {
230 static_assert(sizeof(waiter_type) == sizeof(waiter_pool_base),
231 "waiter_for should be same size with waiter_pool_base");
232 auto& res = waiter_pool_base::waiter_for(addr);
233 return reinterpret_cast<waiter_type&>(res);
234 }
235
241 template <typename U>
242 explicit waiter_base(const U* addr) noexcept
243 : waiter_(waiter_base::waiter_for(addr)),
244 addr_(waiter_base::waiter_wait_addr(addr, &waiter_.value)) {}
245
251 void waiter_notify(bool all, bool bare = false) noexcept {
252 waiter_.waiter_notify(addr_, all, bare);
253 }
254
258 template <typename U, typename Func, typename Spin = default_spin_policy>
259 static bool waiter_do_spin_v(platform_wait_t* addr, const U& old,
260 Func f, platform_wait_t& value, Spin spin = Spin{}) {
261 auto const pred = [=] {
262 return _MSTL memory_compare<U>(old, f()) != 0;
263 };
264 waiter_base::waiter_do_spin_v_impl(addr, old, value);
265 return _MSTL atomic_spin(pred, spin);
266 }
267
271 template <typename U, typename Func, typename Spin = default_spin_policy>
272 bool waiter_do_spin_v(const U& old, Func f, platform_wait_t& value, Spin spin = Spin{}) {
273 return waiter_base::waiter_do_spin_v(addr_, old, f, value, spin);
274 }
275
279 template <typename Pred, typename Spin = default_spin_policy>
280 static bool waiter_do_spin(const platform_wait_t* addr, Pred pred,
281 platform_wait_t& value, Spin spin = Spin{}) {
282#ifdef MSTL_PLATFORM_WINDOWS__
283 value = ::_InterlockedExchangeAdd(const_cast<volatile LONG*>(addr), 0);
284#else
285 __atomic_load(addr, &value, __ATOMIC_ACQUIRE);
286#endif
287 return _MSTL atomic_spin(pred, spin);
288 }
289
293 template <typename Pred, typename Spin = default_spin_policy>
294 bool waiter_do_spin(Pred pred, platform_wait_t& value, Spin spin = Spin{}) {
295 return waiter_base::waiter_do_spin(addr_, pred, value, spin);
296 }
297};
298
299
307template <typename EntersWait>
308struct waiter : waiter_base<waiter_pool> {
309public:
310 using base_type = waiter_base<waiter_pool>;
311
312private:
313 template <bool Wait = EntersWait::value, enable_if_t<Wait, int> = 0>
314 MSTL_ALWAYS_INLINE void enter() const noexcept {
315 waiter_.waiter_enter_wait();
316 }
317 template <bool Wait = EntersWait::value, enable_if_t<!Wait, int> = 0>
318 MSTL_ALWAYS_INLINE void enter() const noexcept {}
319
320 template <bool Wait = EntersWait::value, enable_if_t<Wait, int> = 0>
321 MSTL_ALWAYS_INLINE void leave() const noexcept {
322 waiter_.waiter_leave_wait();
323 }
324 template <bool Wait = EntersWait::value, enable_if_t<!Wait, int> = 0>
325 MSTL_ALWAYS_INLINE void leave() const noexcept {}
326
327public:
333 template <typename T>
334 explicit waiter(const T* addr) noexcept
335 : base_type(addr) {
336 enter();
337 }
338
342 ~waiter() {
343 leave();
344 }
345
355 template <typename T, typename Func>
356 void waiter_do_wait_v(T old, Func f) {
357 do {
358 platform_wait_t value;
359 if (base_type::waiter_do_spin_v(old, f, value)) return;
360 waiter_.waiter_do_wait(base_type::addr_, value);
361 } while (_MSTL memory_compare<T>(old, f()) == 0);
362 }
363
369 template <typename Pred>
370 void waiter_do_wait(Pred pred) noexcept {
371 do {
372 platform_wait_t value;
373 if (base_type::waiter_do_spin(pred, value)) return;
374 waiter_.waiter_do_wait(base_type::addr_, value);
375 } while (!pred());
376 }
377};
378
380using enters_wait = waiter<true_type>;
381
383using bare_wait = waiter<false_type>;
384
387
398template <typename T, typename Func>
399void atomic_wait_address_v(const T* addr, T old, Func f) noexcept {
400 _INNER enters_wait waiter(addr);
401 waiter.waiter_do_wait_v(old, f);
402}
403
413template <typename T, typename Pred>
414void atomic_wait_address(const T* addr, Pred pred) noexcept {
415 _INNER enters_wait waiter(addr);
416 waiter.waiter_do_wait(pred);
417}
418
428template <typename T>
429void atomic_notify_address(const T* addr, const bool all) noexcept {
430 _INNER bare_wait waiter(addr);
431 waiter.waiter_notify(all);
432}
433 // AtomicOperations
435
437#endif // MSTL_CORE_ASYNC_ATOMIC_WAIT_HPP__
MSTL快速用户空间互斥锁
void atomic_wait_address(const T *addr, Pred pred) noexcept
基于谓词的原子等待
bool atomic_spin(Pred &pred, Spin spin=Spin{}) noexcept
原子自旋等待
void atomic_wait_address_v(const T *addr, T old, Func f) noexcept
基于值的原子等待
void atomic_notify_address(const T *addr, const bool all) noexcept
原子通知
void MSTL_API futex_notify(void *addr, bool all) noexcept
通知等待的线程
int platform_wait_t
平台等待类型别名
void MSTL_API futex_wait(void *addr, platform_wait_t value) noexcept
无限期等待FUTEX
@ wait
等待操作
MSTL_CONSTEXPR14 void * memory_copy(void *MSTL_RESTRICT dest, const void *MSTL_RESTRICT src, size_t count) noexcept
从源内存复制到目标内存
MSTL_PURE_FUNCTION MSTL_CONSTEXPR14 int memory_compare(const void *lhs, const void *rhs, size_t count) noexcept
比较两个内存区域的内容
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
uint64_t uintptr_t
可容纳指针的无符号整数类型
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
MSTL内存操作函数
默认自旋策略
MSTL当前线程操作