NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
stop_token.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_ASYNC_STOP_TOKEN_HPP__
2#define NEFORCE_CORE_ASYNC_STOP_TOKEN_HPP__
3
10
15NEFORCE_BEGIN_NAMESPACE__
16
22
28
29class stop_source;
30
31
38class stop_token {
39private:
46 struct stop_callback_node {
47 using callback_type = void(stop_callback_node*)
48#ifdef NEFORCE_STANDARD_17
49 noexcept
50#endif
51 ;
52
53 callback_type* callback;
54 stop_callback_node* prev = nullptr;
55 stop_callback_node* next = nullptr;
56 bool* destroyed = nullptr;
57 binary_semaphore done_semaphore{0};
58
63 explicit stop_callback_node(callback_type* cb) :
64 callback(cb) {}
65
69 void run() noexcept { callback(this); }
70 };
71
78 struct stop_state {
79 using value_type = uint32_t;
80 static constexpr value_type stop_requested_bit = 1;
81 static constexpr value_type locked_bit = 2;
82 static constexpr value_type ssrc_counter_inc = 4;
83
84 atomic<value_type> owners{1};
85 atomic<value_type> value{ssrc_counter_inc};
86 stop_callback_node* head = nullptr;
87 thread::id requester_thread_id;
88
89 stop_state() = default;
90
95 bool stop_possible() noexcept { return value.load(memory_order_acquire) & ~locked_bit; }
96
101 bool stop_requested() noexcept { return value.load(memory_order_acquire) & stop_requested_bit; }
102
106 void add_owner() noexcept { owners.fetch_add(1, memory_order_relaxed); }
107
112 void release_ownership() noexcept {
113 if (owners.fetch_sub(1, memory_order_acq_rel) == 1) {
114 delete this;
115 }
116 }
117
121 void add_stop_source() noexcept { value.fetch_add(ssrc_counter_inc, memory_order_relaxed); }
122
126 void remove_stop_source() noexcept { value.fetch_sub(ssrc_counter_inc, memory_order_release); }
127
131 void lock() noexcept {
132 auto old_value = value.load(memory_order_relaxed);
133 while (!try_lock(old_value, memory_order_relaxed)) {
134 }
135 }
136
140 void unlock() noexcept { value.fetch_sub(locked_bit, memory_order_release); }
141
148 bool request_stop() noexcept {
149 auto old_value = value.load(memory_order_acquire);
150 do {
151 if (old_value & stop_requested_bit) {
152 return false;
153 }
154 } while (!try_lock_and_stop(old_value));
155
156 requester_thread_id = this_thread::id();
157
158 while (head) {
159 bool last_callback;
160 stop_callback_node* callback_node = head;
161 head = head->next;
162 if (head) {
163 head->prev = nullptr;
164 last_callback = false;
165 } else {
166 last_callback = true;
167 }
168 unlock();
169
170 bool destroyed = false;
171 callback_node->destroyed = &destroyed;
172 callback_node->run();
173 if (!destroyed) {
174 callback_node->destroyed = nullptr;
175 callback_node->done_semaphore.release();
176 }
177
178 if (last_callback) {
179 return true;
180 }
181 lock();
182 }
183 unlock();
184 return true;
185 }
186
194 bool register_callback(stop_callback_node* callback_node) noexcept {
195 auto old_value = value.load(memory_order_acquire);
196 do {
197 if (old_value & stop_requested_bit) {
198 callback_node->run();
199 return false;
200 }
201 if (old_value < ssrc_counter_inc) {
202 return false;
203 }
204 } while (!try_lock(old_value));
205
206 callback_node->next = head;
207 if (head) {
208 head->prev = callback_node;
209 }
210 head = callback_node;
211 unlock();
212 return true;
213 }
214
221 void remove_callback(stop_callback_node* callback_node) {
222 lock();
223
224 if (callback_node == head) {
225 head = head->next;
226 if (head) {
227 head->prev = nullptr;
228 }
229 unlock();
230 return;
231 }
232 if (callback_node->prev) {
233 callback_node->prev->next = callback_node->next;
234 if (callback_node->next) {
235 callback_node->next->prev = callback_node->prev;
236 }
237 unlock();
238 return;
239 }
240
241 unlock();
242
243 if (requester_thread_id != this_thread::id()) {
244 callback_node->done_semaphore.acquire();
245 return;
246 }
247
248 if (callback_node->destroyed) {
249 *callback_node->destroyed = true;
250 }
251 }
252
259 bool try_lock(value_type& current_value, const memory_order failure_order = memory_order_acquire) noexcept {
260 return do_try_lock(current_value, 0, memory_order_acquire, failure_order);
261 }
262
268 bool try_lock_and_stop(value_type& current_value) noexcept {
269 return do_try_lock(current_value, stop_requested_bit, memory_order_acq_rel, memory_order_acquire);
270 }
271
275 bool do_try_lock(value_type& current_value, value_type new_bits, const memory_order success_order,
276 const memory_order failure_order) noexcept {
277 if (current_value & locked_bit) {
278 this_thread::relax();
279 current_value = value.load(failure_order);
280 return false;
281 }
282 new_bits |= locked_bit;
283 return value.compare_exchange_weak(current_value, current_value | new_bits, success_order, failure_order);
284 }
285 };
286
293 struct stop_state_reference {
294 private:
295 stop_state* ptr_ = nullptr;
296
297 public:
298 stop_state_reference() = default;
299
304 explicit stop_state_reference(const stop_source& ref) :
305 ptr_(new stop_state()) {}
306
311 stop_state_reference(const stop_state_reference& other) noexcept :
312 ptr_(other.ptr_) {
313 if (ptr_) {
314 ptr_->add_owner();
315 }
316 }
317
322 stop_state_reference(stop_state_reference&& other) noexcept :
323 ptr_(other.ptr_) {
324 other.ptr_ = nullptr;
325 }
326
330 stop_state_reference& operator=(const stop_state_reference& other) noexcept {
331 const auto new_ptr = other.ptr_;
332 if (new_ptr != ptr_) {
333 if (new_ptr) {
334 new_ptr->add_owner();
335 }
336 if (ptr_) {
337 ptr_->release_ownership();
338 }
339 ptr_ = new_ptr;
340 }
341 return *this;
342 }
343
347 stop_state_reference& operator=(stop_state_reference&& other) noexcept {
348 stop_state_reference(move(other)).swap(*this);
349 return *this;
350 }
351
355 ~stop_state_reference() {
356 if (ptr_) {
357 ptr_->release_ownership();
358 }
359 }
360
364 void swap(stop_state_reference& other) noexcept { _NEFORCE swap(ptr_, other.ptr_); }
365
369 explicit operator bool() const noexcept { return ptr_ != nullptr; }
370
374 stop_state* operator->() const noexcept { return ptr_; }
375
379 bool operator==(const stop_state_reference& rhs) const noexcept { return ptr_ == rhs.ptr_; }
380
384 bool operator!=(const stop_state_reference& rhs) const noexcept { return ptr_ != rhs.ptr_; }
385 };
386
387private:
388 stop_state_reference state_ref_;
389
390 friend class stop_source;
391
392 template <typename Callback>
393 friend class stop_callback;
394
399 explicit stop_token(stop_state_reference state_ref) noexcept :
400 state_ref_{move(state_ref)} {}
401
402public:
403 stop_token() noexcept = default;
404 ~stop_token() = default;
405 stop_token(const stop_token&) noexcept = default;
406 stop_token& operator=(const stop_token&) noexcept = default;
407 stop_token(stop_token&&) noexcept = default;
408 stop_token& operator=(stop_token&&) noexcept = default;
409
414 NEFORCE_NODISCARD bool stop_possible() const noexcept {
415 return static_cast<bool>(state_ref_) && state_ref_->stop_possible();
416 }
417
422 NEFORCE_NODISCARD bool stop_requested() const noexcept {
423 return static_cast<bool>(state_ref_) && state_ref_->stop_requested();
424 }
425
430 void swap(stop_token& other) noexcept { state_ref_.swap(other.state_ref_); }
431
439 NEFORCE_NODISCARD bool operator==(const stop_token& rhs) const { return state_ref_ == rhs.state_ref_; }
440};
441
442
451private:
452 stop_token::stop_state_reference state_ref_;
453
454public:
461 state_ref_(*this) {}
462
469 explicit stop_source(none_t none) noexcept {}
470
475 stop_source(const stop_source& other) noexcept :
476 state_ref_(other.state_ref_) {
477 if (state_ref_) {
478 state_ref_->add_stop_source();
479 }
480 }
481
482 stop_source(stop_source&&) noexcept = default;
483
487 stop_source& operator=(const stop_source& other) noexcept {
488 if (state_ref_ != other.state_ref_) {
489 stop_source sink(move(*this));
490 state_ref_ = other.state_ref_;
491 if (state_ref_) {
492 state_ref_->add_stop_source();
493 }
494 }
495 return *this;
496 }
497
498 stop_source& operator=(stop_source&&) noexcept = default;
499
506 if (state_ref_) {
507 state_ref_->remove_stop_source();
508 }
509 }
510
515 NEFORCE_NODISCARD bool stop_possible() const noexcept { return static_cast<bool>(state_ref_); }
516
521 NEFORCE_NODISCARD bool stop_requested() noexcept { return stop_possible() && state_ref_->stop_requested(); }
522
529 NEFORCE_NODISCARD bool request_stop() noexcept {
530 if (stop_possible()) {
531 return state_ref_->request_stop();
532 }
533 return false;
534 }
535
540 NEFORCE_NODISCARD stop_token get_token() const noexcept { return stop_token{state_ref_}; }
541
546 void swap(stop_source& other) noexcept { state_ref_.swap(other.state_ref_); }
547
551 NEFORCE_NODISCARD bool operator==(const stop_source& rhs) const noexcept { return state_ref_ == rhs.state_ref_; }
552
556 NEFORCE_NODISCARD bool operator!=(const stop_source& rhs) const noexcept { return state_ref_ != rhs.state_ref_; }
557};
558
559
571template <typename Callback>
572class NEFORCE_NODISCARD stop_callback {
573 static_assert(is_nothrow_destructible_v<Callback>, "Callback should be nothrow destructible.");
574 static_assert(is_invocable_v<Callback>, "Callback should be invocable.");
575
576public:
577 using callback_type = Callback;
578
579private:
580 struct callback_impl : stop_token::stop_callback_node {
581 template <typename Cb>
582 explicit callback_impl(Cb&& callback) :
583 stop_callback_node(&execute_callback),
584 callback(forward<Cb>(callback)) {}
585
586 Callback callback;
587
588 static void execute_callback(stop_callback_node* node) noexcept {
589 Callback& cb = static_cast<callback_impl*>(node)->callback;
590 forward<Callback>(cb)();
591 }
592 };
593
594 callback_impl callback_impl;
595 stop_token::stop_state_reference state_ref_;
596
597public:
604 template <typename Cb, enable_if_t<is_constructible_v<Callback, Cb>, int> = 0>
605 explicit stop_callback(const stop_token& token, Cb&& callback) noexcept(is_nothrow_constructible_v<Callback, Cb>) :
606 callback_impl(forward<Cb>(callback)) {
607 if (auto state_ref = token.state_ref_) {
608 if (state_ref->register_callback(&callback_impl)) {
609 state_ref_.swap(state_ref);
610 }
611 }
612 }
613
620 template <typename Cb, enable_if_t<is_constructible_v<Callback, Cb>, int> = 0>
621 explicit stop_callback(stop_token&& token, Cb&& callback) noexcept(is_nothrow_constructible_v<Callback, Cb>) :
622 callback_impl(forward<Cb>(callback)) {
623 if (auto& state_ref = token.state_ref_) {
624 if (state_ref->register_callback(&callback_impl)) {
625 state_ref_.swap(state_ref);
626 }
627 }
628 }
629
630 stop_callback(const stop_callback&) = delete;
634
641 if (state_ref_) {
642 state_ref_->remove_callback(&callback_impl);
643 }
644 }
645};
646
647#ifdef NEFORCE_STANDARD_17
648template <typename Callback>
650#endif
651 // StopTokens
653 // AsyncComponents
655
656NEFORCE_END_NAMESPACE__
657#endif // NEFORCE_CORE_ASYNC_STOP_TOKEN_HPP__
原子类型完整实现
void acquire() noexcept
获取信号量
void release(const platform_wait_t update=1) noexcept
释放信号量
锁管理器模板
停止回调类模板
stop_callback(const stop_callback &)=delete
禁止拷贝构造
stop_callback & operator=(const stop_callback &)=delete
禁止拷贝赋值
Callback callback_type
回调函数类型
~stop_callback()
析构函数
stop_callback(stop_callback &&)=delete
禁止移动构造
stop_callback(const stop_token &token, Cb &&callback) noexcept(is_nothrow_constructible_v< Callback, Cb >)
左值构造函数
stop_callback(stop_token &&token, Cb &&callback) noexcept(is_nothrow_constructible_v< Callback, Cb >)
右值构造函数
stop_callback & operator=(stop_callback &&)=delete
禁止移动赋值
stop_source(stop_source &&) noexcept=default
移动构造函数
stop_source(none_t none) noexcept
构造函数
NEFORCE_NODISCARD bool request_stop() noexcept
请求停止
NEFORCE_NODISCARD stop_token get_token() const noexcept
获取停止令牌
stop_source()
默认构造函数
void swap(stop_source &other) noexcept
交换两个停止源
NEFORCE_NODISCARD bool stop_requested() noexcept
检查是否已请求停止
stop_source(const stop_source &other) noexcept
拷贝构造函数
NEFORCE_NODISCARD bool operator!=(const stop_source &rhs) const noexcept
不等比较运算符
stop_source & operator=(stop_source &&) noexcept=default
移动赋值运算符
NEFORCE_NODISCARD bool stop_possible() const noexcept
检查是否具有停止能力
NEFORCE_NODISCARD bool operator==(const stop_source &rhs) const noexcept
相等比较运算符
停止令牌类
NEFORCE_NODISCARD bool operator==(const stop_token &rhs) const
相等比较运算符
stop_token() noexcept=default
默认构造函数
void swap(stop_token &other) noexcept
交换两个停止令牌
stop_token & operator=(const stop_token &) noexcept=default
拷贝赋值运算符
NEFORCE_NODISCARD bool stop_possible() const noexcept
检查是否可能收到停止请求
NEFORCE_NODISCARD bool stop_requested() const noexcept
检查是否已收到停止请求
NEFORCE_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
unsigned int uint32_t
32位无符号整数类型
bool operator!=(const function< Res(Args...)> &f, nullptr_t np) noexcept
不等于空指针比较
NEFORCE_INLINE17 constexpr bool is_invocable_v
is_invocable的便捷变量模板
constexpr Iterator prev(Iterator iter, iter_difference_t< Iterator > n=-1)
获取迭代器的前一个位置
constexpr Iterator next(Iterator iter, iter_difference_t< Iterator > n=1)
获取迭代器的后一个位置
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
获取内存顺序常量
memory_order
内存顺序
NEFORCE_INLINE17 constexpr try_lock_tag try_lock
尝试锁定标签实例
NEFORCE_INLINE17 constexpr none_t none
默认空表示
NEFORCE_NODISCARD constexpr reference_wrapper< T > ref(T &val) noexcept
创建引用包装器
atomic_semaphore< 1 > binary_semaphore
二元信号量
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
void swap()=delete
删除无参数的swap重载
NEFORCE_INLINE17 constexpr bool is_nothrow_constructible_v
is_nothrow_constructible的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_nothrow_destructible_v
is_nothrow_destructible的便捷变量模板
空状态类型
信号量支持
通用原子类型模板
T load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
bool compare_exchange_weak(T &expected, T desired, const memory_order success, const memory_order failure) noexcept
弱比较交换操作
空状态类型
线程唯一标识符类
线程管理类