NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
atomic_futex.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_ASYNC_ATOMIC_FUTEX_HPP__
2#define NEFORCE_CORE_ASYNC_ATOMIC_FUTEX_HPP__
3
11
14NEFORCE_BEGIN_NAMESPACE__
15
21
27
36template <uint32_t WaiterBit = 0x80000000>
38 atomic<uint32_t> data_;
39
52 uint32_t load_and_test_until(uint32_t assumed, const uint32_t operand, const bool equal, const memory_order mo,
53 const bool has_timeout, const int64_t sec, const int64_t ns) {
54 for (;;) {
55 data_.fetch_or(WaiterBit, memory_order_relaxed);
56 const bool ret = futex_wait_until(&data_, assumed | WaiterBit, has_timeout, sec, ns, false);
57 assumed = load(mo);
58 if (!ret || ((operand == assumed) == equal)) {
59 return assumed;
60 }
61 }
62 }
63
76 uint32_t load_and_test_until_steady(uint32_t assumed, const uint32_t operand, const bool equal,
77 const memory_order mo, const bool has_timeout, const int64_t sec,
78 const int64_t ns) {
79 for (;;) {
80 data_.fetch_or(WaiterBit, memory_order_relaxed);
81 const bool ret = futex_wait_until(&data_, assumed | WaiterBit, has_timeout, sec, ns, true);
82 assumed = load(mo);
83 if (!ret || ((operand == assumed) == equal)) {
84 return assumed;
85 }
86 }
87 }
88
97 uint32_t load_and_test(const uint32_t assumed, const uint32_t operand, const bool equal, const memory_order mo) {
98 return load_and_test_until(assumed, operand, equal, mo, false, 0, 0);
99 }
100
111 template <typename Dur>
112 uint32_t load_and_test_until_impl(uint32_t assumed, uint32_t operand, bool equal, memory_order mo,
113 const time_point<system_clock, Dur>& atime) {
114 auto sec = atime.to_sec();
115 const auto ns = nanoseconds(atime - sec).count();
116 return this->load_and_test_until(assumed, operand, equal, mo, true, sec.since_epoch().count(), ns);
117 }
118
129 template <typename Dur>
130 uint32_t load_and_test_until_impl(uint32_t assumed, uint32_t operand, bool equal, memory_order mo,
131 const time_point<steady_clock, Dur>& atime) {
132 auto sec = atime.to_sec();
133 const auto ns = nanoseconds(atime - sec).count();
134 return this->load_and_test_until_steady(assumed, operand, equal, mo, true, sec.since_epoch().count(), ns);
135 }
136
137public:
142 explicit constexpr atomic_futex(const uint32_t data) :
143 data_(data) {}
144
152 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE uint32_t load(const memory_order mo) const noexcept {
153 return data_.load(mo) & ~WaiterBit;
154 }
155
164 NEFORCE_ALWAYS_INLINE uint32_t load_when_not_equal(const uint32_t value, const memory_order mo) {
165 const uint32_t old = load(mo);
166 if ((old & ~WaiterBit) != value) {
167 return (old & ~WaiterBit);
168 }
169 return load_and_test(old, value, false, mo);
170 }
171
179 NEFORCE_ALWAYS_INLINE void load_when_equal(const uint32_t value, const memory_order mo) {
180 const uint32_t old = load(mo);
181 if ((old & ~WaiterBit) == value) {
182 return;
183 }
184 load_and_test(old, value, true, mo);
185 }
186
196 template <typename Rep, typename Period>
197 NEFORCE_ALWAYS_INLINE bool load_when_equal_for(const uint32_t value, const memory_order mo,
198 const duration<Rep, Period>& rtime) {
199 const auto atime = steady_clock::now() + ceil<steady_clock::duration>(rtime);
200 return this->load_when_equal_until(value, mo, atime);
201 }
202
214 template <typename Clock, typename Dur>
215 NEFORCE_ALWAYS_INLINE bool load_when_equal_until(const uint32_t value, const memory_order mo,
216 const time_point<Clock, Dur>& atime) {
217 auto now = Clock::now();
218 do {
219 const auto s_atime = steady_clock::now() + ceil<steady_clock::duration>(atime - now);
220 if (this->load_when_equal_until(value, mo, s_atime)) {
221 return true;
222 }
223 now = Clock::now();
224 } while (now < atime);
225 return false;
226 }
227
236 template <typename Dur>
237 NEFORCE_ALWAYS_INLINE bool load_when_equal_until(const uint32_t value, const memory_order mo,
238 const time_point<system_clock, Dur>& atime) {
239 uint32_t old = load(mo);
240 if ((old & ~WaiterBit) == value) {
241 return true;
242 }
243 old = this->load_and_test_until_impl(old, value, true, mo, atime);
244 return (old & ~WaiterBit) == value;
245 }
246
255 template <typename Dur>
256 NEFORCE_ALWAYS_INLINE bool load_when_equal_until(const uint32_t value, const memory_order mo,
257 const time_point<steady_clock, Dur>& atime) {
258 uint32_t old = load(mo);
259 if ((old & ~WaiterBit) == value) {
260 return true;
261 }
262 old = this->load_and_test_until_impl(old, value, true, mo, atime);
263 return (old & ~WaiterBit) == value;
264 }
265
275 NEFORCE_ALWAYS_INLINE bool compare_exchange_strong(uint32_t& expected, const uint32_t desired,
276 const memory_order success,
277 const memory_order failure) noexcept {
278 return data_.compare_exchange_strong(expected, desired, success, failure);
279 }
280
288 NEFORCE_ALWAYS_INLINE void store_notify_all(const uint32_t value, const memory_order mo) noexcept {
289 auto* const futex = static_cast<uint32_t*>(static_cast<void*>(&data_));
290 if ((data_.exchange(value, mo) & WaiterBit) != 0U) {
291 _NEFORCE futex_notify(futex, true);
292 }
293 }
294};
295 // Futex
297 // AsyncComponents
299
300NEFORCE_END_NAMESPACE__
301#endif // NEFORCE_CORE_ASYNC_ATOMIC_FUTEX_HPP__
原子类型完整实现
uint32_t load(const memory_order mo) const noexcept
原子加载数据
bool load_when_equal_until(const uint32_t value, const memory_order mo, const time_point< steady_clock, Dur > &atime)
在指定时间点前等待值等于指定值(单调时钟)
void load_when_equal(const uint32_t value, const memory_order mo)
等待直到值等于指定值
void store_notify_all(const uint32_t value, const memory_order mo) noexcept
存储新值并通知所有等待线程
bool load_when_equal_until(const uint32_t value, const memory_order mo, const time_point< system_clock, Dur > &atime)
在指定时间点前等待值等于指定值(系统时钟)
uint32_t load_when_not_equal(const uint32_t value, const memory_order mo)
等待直到值不等于指定值
constexpr atomic_futex(const uint32_t data)
构造函数
bool load_when_equal_for(const uint32_t value, const memory_order mo, const duration< Rep, Period > &rtime)
在指定时间内等待值等于指定值
bool load_when_equal_until(const uint32_t value, const memory_order mo, const time_point< Clock, Dur > &atime)
在指定时间点前等待值等于指定值(通用时钟)
bool compare_exchange_strong(uint32_t &expected, const uint32_t desired, const memory_order success, const memory_order failure) noexcept
原子比较并交换
时钟类型
constexpr bool equal(Iterator1 first1, Iterator1 last1, Iterator2 first2, BinaryPredicate binary_pred) noexcept(noexcept(++first1) &&noexcept(++first2) &&noexcept(binary_pred(*first1, *first2)))
比较两个范围是否相等
unsigned int uint32_t
32位无符号整数类型
long long int64_t
64位有符号整数类型
duration< int64_t, nano > nanoseconds
纳秒持续时间
bool futex_wait_until(const platform_wait_t *addr, platform_wait_t old, const time_point< Clock, Dur > &timeout)
FUTEX定时等待函数
void futex_notify(void *addr, bool all) noexcept
通知等待的线程
constexpr decimal_t ceil(const decimal_t x) noexcept
向上取整
constexpr auto memory_order_relaxed
宽松内存顺序常量
memory_order
内存顺序
constexpr decltype(auto) data(Container &cont) noexcept(noexcept(cont.data()))
获取容器的底层数据指针
通用原子类型模板
持续时间类模板
constexpr rep count() const noexcept
获取计数值
static time_point now() noexcept
获取当前时间点
时间点类模板