NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
generator.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_ASYNC_GENERATOR_HPP__
2#define NEFORCE_CORE_ASYNC_GENERATOR_HPP__
3
13
15#if defined(NEFORCE_STANDARD_20) || defined(NEXUSFORCE_ENABLE_DOXYGEN)
19NEFORCE_BEGIN_NAMESPACE__
20
26
35public:
44
49 bool await_ready() const noexcept { return token && token->is_cancelled(); }
50
55 void await_suspend(coroutine_handle<> h) const noexcept {}
56
61 void await_resume() const {
62 if (token && token->is_cancelled()) {
63 NEFORCE_THROW_EXCEPTION(exception("Operation cancelled"));
64 }
65 }
66 };
67
68private:
69 struct state {
70 atomic<bool> cancelled{false};
71 atomic<size_t> ref_count{1};
72 };
73 state* state_;
74
78 void release() {
79 if (state_ && state_->ref_count.fetch_sub(1, memory_order_acq_rel) == 1) {
80 delete state_;
81 }
82 }
83
84public:
89 state_(new state()) {}
90
96 state_(other.state_) {
97 if (state_) {
98 state_->ref_count.fetch_add(1, memory_order_relaxed);
99 }
100 }
101
108 if (addressof(other) == this) {
109 return *this;
110 }
111
112 release();
113 state_ = other.state_;
114 if (state_) {
115 state_->ref_count.fetch_add(1, memory_order_relaxed);
116 }
117 return *this;
118 }
119
123 ~cancellation_token() { release(); }
124
128 void cancel() noexcept {
129 if (state_) {
130 state_->cancelled.store(true, memory_order_release);
131 }
132 }
133
138 bool is_cancelled() const noexcept { return state_ && state_->cancelled.load(memory_order_acquire); }
139
144 check_awaiter check() const { return check_awaiter{this}; }
145};
146
147
156template <typename T>
158public:
166
172
177 suspend_always initial_suspend() noexcept { return {}; }
178
183 suspend_always final_suspend() noexcept { return {}; }
184
191 current_value = _NEFORCEmove(value);
192 return {};
193 }
194
198 void return_void() noexcept {}
199
204 };
205
210 struct iterator {
211 using iterator_category = input_iterator_tag;
212 using value_type = T;
213 using difference_type = ptrdiff_t;
214 using pointer = T*;
215 using reference = T&;
216
218
222 iterator() = default;
223
230
236 handle.resume();
237 if (handle.done()) {
238 handle = nullptr;
239 }
240 return *this;
241 }
242
246 void operator++(int) { ++(*this); }
247
252 T& operator*() const noexcept {
253 NEFORCE_CONSTEXPR_ASSERT(handle.promise().current_value.has_value());
254 return *handle.promise().current_value;
255 }
256
261 T* operator->() const noexcept { return &(*handle.promise().current_value); }
262
268 bool operator==(const iterator& other) const noexcept { return handle == other.handle; }
269
275 bool operator!=(const iterator& other) const noexcept { return !(*this == other); }
276 };
277
278private:
280
281public:
287 handle_(h) {}
288
293 generator(generator&& other) noexcept :
294 handle_(other.handle_) {
295 other.handle_ = nullptr;
296 }
297
303 generator& operator=(generator&& other) noexcept {
304 if (addressof(other) == this) {
305 return *this;
306 }
307
308 if (handle_) {
309 handle_.destroy();
310 }
311 handle_ = other.handle_;
312 other.handle_ = nullptr;
313
314 return *this;
315 }
316
321 if (handle_) {
322 handle_.destroy();
323 }
324 }
325
326 generator(const generator&) = delete;
327 generator& operator=(const generator&) = delete;
328
334 if (handle_) {
335 handle_.resume();
336 if (handle_.promise().exception) {
337 _NEFORCE rethrow_exception(handle_.promise().exception);
338 }
339 if (handle_.done()) {
340 return iterator{nullptr};
341 }
342 }
343 return iterator{handle_};
344 }
345
350 iterator end() { return iterator{nullptr}; }
351
358 template <typename F>
360 for (auto&& value: *this) {
361 co_yield func(_NEFORCE forward<decltype(value)>(value));
362 }
363 }
364
371 template <typename Pred>
372 generator filter(Pred&& pred) {
373 for (auto&& value: *this) {
374 if (pred(value)) {
375 co_yield _NEFORCE forward<decltype(value)>(value);
376 }
377 }
378 }
379
385 generator take(const size_t n) {
386 size_t count = 0;
387 for (auto&& value: *this) {
388 if (count >= n) {
389 break;
390 }
391 co_yield _NEFORCE forward<decltype(value)>(value);
392 ++count;
393 }
394 }
395
401 generator skip(const size_t n) {
402 size_t count = 0;
403 for (auto&& value: *this) {
404 if (count < n) {
405 ++count;
406 continue;
407 }
408 co_yield _NEFORCE forward<decltype(value)>(value);
409 }
410 }
411
418 for (auto&& value: *this) {
419 co_yield _NEFORCE forward<decltype(value)>(value);
420 }
421 for (auto&& value: other) {
422 co_yield _NEFORCE forward<decltype(value)>(value);
423 }
424 }
425
431 template <typename F>
432 void for_each(F&& func) {
433 for (auto&& value: *this) {
434 func(_NEFORCE forward<decltype(value)>(value));
435 }
436 }
437
446 template <typename Acc, typename F>
447 Acc fold(Acc init, F&& func) {
448 Acc result = _NEFORCE move(init);
449 for (auto&& value: *this) {
450 result = func(_NEFORCE move(result), _NEFORCE forward<decltype(value)>(value));
451 }
452 return result;
453 }
454};
455
456
465template <typename T>
466class task {
467public:
482 bool await_ready() noexcept { return false; }
483
490 auto& promise = h.promise();
491 if (promise.continuation) {
492 return promise.continuation;
493 }
494 return noop_coroutine();
495 }
496
500 void await_resume() noexcept {}
501 };
502
507
513
519
524 bool is_cancelled() const noexcept { return token && token->is_cancelled(); }
525
530 suspend_always initial_suspend() noexcept { return {}; }
531
536 final_awaiter final_suspend() noexcept { return {}; }
537
542 void return_value(T value) { result = _NEFORCE move(value); }
543
548 };
549
554 struct awaiter {
556
561 bool await_ready() const noexcept { return handle.done(); }
562
569 handle.promise().continuation = continuation;
570 return handle;
571 }
572
578 if (handle.promise().exception) {
579 _NEFORCE rethrow_exception(handle.promise().exception);
580 }
581 return _NEFORCE move(*handle.promise().result);
582 }
583 };
584
585private:
587
588public:
594 handle_(h) {}
595
600 task(task&& other) noexcept :
601 handle_(other.handle_) {
602 other.handle_ = nullptr;
603 }
604
610 task& operator=(task&& other) noexcept {
611 if (addressof(other) == this) {
612 return *this;
613 }
614
615 if (handle_) {
616 handle_.destroy();
617 }
618 handle_ = other.handle_;
619 other.handle_ = nullptr;
620
621 return *this;
622 }
623
628 if (handle_) {
629 handle_.destroy();
630 }
631 }
632
633 task(const task&) = delete;
634 task& operator=(const task&) = delete;
635
640 awaiter operator co_await() { return awaiter{handle_}; }
641
646 bool done() const noexcept { return handle_.done(); }
647
651 void resume() {
652 if (handle_ && !handle_.done()) {
653 handle_.resume();
654 }
655 }
656
661 T get() {
662 while (!handle_.done()) {
663 handle_.resume();
664 }
665 if (handle_.promise().exception) {
666 _NEFORCE rethrow_exception(handle_.promise().exception);
667 }
668 return _NEFORCE move(*handle_.promise().result);
669 }
670
676 if (handle_) {
677 handle_.promise().set_cancellation_token(&token);
678 }
679 }
680
685 bool is_cancelled() const noexcept { return handle_ && handle_.promise().is_cancelled(); }
686};
687
688
692template <>
693class task<void> {
694public:
695 struct promise_type {
698 cancellation_token* token = nullptr;
699
701
703
704 bool is_cancelled() const { return token && token->is_cancelled(); }
705
706 suspend_always initial_suspend() noexcept { return {}; }
707
708 struct final_awaiter {
709 bool await_ready() noexcept { return false; }
710
712 auto& promise = h.promise();
713 if (promise.continuation) {
714 return promise.continuation;
715 }
716 return noop_coroutine();
717 }
718
719 void await_resume() noexcept {}
720 };
721
722 final_awaiter final_suspend() noexcept { return {}; }
723
724 void return_void() noexcept {}
725
727 };
728
729 struct awaiter {
731
732 bool await_ready() const noexcept { return handle.done(); }
733
735 handle.promise().continuation = continuation;
736 return handle;
737 }
738
739 void await_resume() {
740 if (handle.promise().exception) {
741 rethrow_exception(handle.promise().exception);
742 }
743 }
744 };
745
746private:
748
749public:
751 handle_(h) {}
752
753 task(task&& other) noexcept :
754 handle_(other.handle_) {
755 other.handle_ = nullptr;
756 }
757
758 task& operator=(task&& other) noexcept {
759 if (addressof(other) == this) {
760 return *this;
761 }
762
763 if (handle_) {
764 handle_.destroy();
765 }
766 handle_ = other.handle_;
767 other.handle_ = nullptr;
768
769 return *this;
770 }
771
772 ~task() {
773 if (handle_) {
774 handle_.destroy();
775 }
776 }
777
778 task(const task&) = delete;
779 task& operator=(const task&) = delete;
780
781 awaiter operator co_await() { return awaiter{handle_}; }
782
783 bool done() const { return handle_.done(); }
784
785 void resume() {
786 if (handle_ && !handle_.done()) {
787 handle_.resume();
788 }
789 }
790
791 void get() {
792 while (!handle_.done()) {
793 handle_.resume();
794 }
795 if (handle_.promise().exception) {
796 rethrow_exception(handle_.promise().exception);
797 }
798 }
799
801 if (handle_) {
802 handle_.promise().set_cancellation_token(&token);
803 }
804 }
805
806 bool is_cancelled() const { return handle_ && handle_.promise().is_cancelled(); }
807};
808
809
811NEFORCE_BEGIN_INNER__
812
813template <typename... Ts>
814struct when_all_result {
815 tuple<Ts...> values;
816};
817
818template <size_t I, typename Tuple, typename... Tasks, enable_if_t<(I < sizeof...(Tasks)), int> = 0>
819task<void> when_all_helper(Tuple& results, Tasks&&... tasks) {
820 auto& current_task = _NEFORCE get<I>(_NEFORCE forward_as_tuple(_NEFORCE forward<Tasks>(tasks)...));
821 _NEFORCE get<I>(results) = co_await _NEFORCE move(current_task);
822 co_await when_all_helper<I + 1>(results, _NEFORCE forward<Tasks>(tasks)...);
823 co_return;
824}
825
826template <size_t I, typename Tuple, typename... Tasks, enable_if_t<I == sizeof...(Tasks), int> = 0>
827task<void> when_all_helper(Tuple&, Tasks&&...) {
828 co_return;
829}
830
831NEFORCE_END_INNER__
833
842template <typename... Tasks>
843auto when_all(Tasks&&... tasks) -> task<tuple<typename Tasks::promise_type::result_type...>> {
844 tuple<typename Tasks::promise_type::result_type...> results;
845 co_await inner::when_all_helper<0>(results, _NEFORCE forward<Tasks>(tasks)...);
846 co_return results;
847}
848
849
861template <typename T, typename Factory>
862task<T> retry(Factory&& factory, const size_t max_attempts,
863 function<bool(const exception_ptr&)> should_retry = nullptr) {
864 static_assert(_NEFORCE is_invocable_r_v<task<T>, Factory>, "Factory must return task<T>");
865
866 exception_ptr last_exception;
867
868 for (size_t attempt = 0; attempt < max_attempts; ++attempt) {
869 try {
870 co_return co_await factory();
871 } catch (...) {
872 last_exception = _NEFORCE current_exception();
873
874 if (should_retry && !should_retry(last_exception)) {
875 rethrow_exception(last_exception);
876 }
877 if (attempt == max_attempts - 1) {
878 rethrow_exception(last_exception);
879 }
880 }
881 }
882
883 rethrow_exception(last_exception);
884}
885 // Coroutine
887
888NEFORCE_END_NAMESPACE__
889#endif // NEFORCE_STANDARD_20
890#endif // NEFORCE_CORE_ASYNC_GENERATOR_HPP__
原子类型完整实现
void cancel() noexcept
请求取消
check_awaiter check() const
获取取消检查等待器
~cancellation_token()
析构函数,释放状态
cancellation_token & operator=(const cancellation_token &other)
拷贝赋值运算符
bool is_cancelled() const noexcept
检查是否已被取消
cancellation_token()
默认构造函数,创建新的取消令牌
cancellation_token(const cancellation_token &other)
拷贝构造函数,共享状态
函数包装器主模板声明
懒序列生成器
generator(coroutine_handle< promise_type > h)
从协程句柄构造
generator skip(const size_t n)
跳过前n个元素
generator take(const size_t n)
取前n个元素
generator chain(generator &&other)
连接两个生成器
generator & operator=(generator &&other) noexcept
移动赋值运算符
invoke_result_t< F, T > map(F &&func)
映射变换
void for_each(F &&func)
遍历每个元素
iterator begin()
获取起始迭代器
generator(generator &&other) noexcept
移动构造函数
Acc fold(Acc init, F &&func)
折叠(归约)
generator filter(Pred &&pred)
过滤
~generator()
析构函数,销毁协程
iterator end()
获取结束迭代器
可选值类
Promise类模板
promise()
默认构造函数
异步任务
void set_cancellation_token(cancellation_token &token)
设置取消令牌
task & operator=(task &&other) noexcept
移动赋值运算符
void resume()
恢复任务执行
T get()
同步获取任务结果
task(task &&other) noexcept
移动构造函数
bool done() const noexcept
检查任务是否已完成
~task()
析构函数,销毁协程
bool is_cancelled() const noexcept
检查任务是否被取消
task(coroutine_handle< promise_type > h)
从协程句柄构造
协程支持
异常指针实现
NEFORCE_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
NEFORCE_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
NEFORCE_ALWAYS_INLINE enable_if_t< is_void_v< T >, future_result_t< T > > get(future< T > &f)
通用future结果获取函数
noop_coroutine_handle noop_coroutine() noexcept
获取空操作协程句柄
std::coroutine_handle< Promise > coroutine_handle
协程句柄
task< T > retry(Factory &&factory, const size_t max_attempts, function< bool(const exception_ptr &)> should_retry=nullptr)
带重试的异步操作
auto when_all(Tasks &&... tasks) -> task< tuple< typename Tasks::promise_type::result_type... > >
等待所有任务完成
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
#define NEFORCE_CONSTEXPR_ASSERT(COND)
编译时常量断言
void NEFORCE_API rethrow_exception(const exception_ptr &p)
重新抛出异常
exception_ptr NEFORCE_API current_exception() noexcept
获取当前异常
NEFORCE_INLINE17 constexpr bool is_invocable_r_v
is_invocable_r的便捷变量模板
typename inner::__invoke_result_aux< F, Args... >::type invoke_result_t
invoke_result的便捷别名
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_ALWAYS_INLINE_INLINE thread::native_handle_type handle() noexcept
获取当前线程句柄
NEFORCE_NODISCARD constexpr tuple< Types &&... > forward_as_tuple(Types &&... args) noexcept
创建转发引用元组
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
可选值类型
通用原子类型模板
bool await_ready() const noexcept
检查是否可立即恢复
const cancellation_token * token
令牌指针
void await_resume() const
恢复时执行的操作
void await_suspend(coroutine_handle<> h) const noexcept
暂停协程(实际上从不暂停)
异常基类
生成器的输入迭代器
T & operator*() const noexcept
解引用,获取当前值
void operator++(int)
后置递增
bool operator!=(const iterator &other) const noexcept
不等比较
bool operator==(const iterator &other) const noexcept
相等比较
coroutine_handle< promise_type > handle
协程句柄
iterator(coroutine_handle< promise_type > h)
从协程句柄构造
T * operator->() const noexcept
箭头操作符
iterator()=default
默认构造函数
iterator & operator++()
前置递增,恢复协程获取下一个值
生成器的promise类型
optional< T > current_value
当前产生的值
void return_void() noexcept
返回void(生成器不返回值)
suspend_always yield_value(T value)
产生一个值
exception_ptr exception
异常指针
void unhandled_exception()
处理未捕获的异常
suspend_always final_suspend() noexcept
最终暂停点
suspend_always initial_suspend() noexcept
初始暂停点
generator get_return_object()
获取生成器对象
输入迭代器标签
始终暂停的等待器
任务等待器
coroutine_handle< promise_type > handle
协程句柄
bool await_ready() const noexcept
检查是否可立即恢复
T await_resume()
恢复时获取结果
coroutine_handle await_suspend(coroutine_handle<> continuation) noexcept
暂停时执行的操作
void await_resume() noexcept
恢复时执行的操作
bool await_ready() noexcept
检查是否可立即恢复
coroutine_handle await_suspend(coroutine_handle< promise_type > h) noexcept
暂停时执行的操作
任务的promise类型
void unhandled_exception() noexcept
处理未捕获的异常
void return_value(T value)
设置返回值
void set_cancellation_token(cancellation_token *t) noexcept
设置取消令牌
final_awaiter final_suspend() noexcept
最终暂停点
optional< T > result
结果值
cancellation_token * token
取消令牌
task get_return_object()
获取任务对象
coroutine_handle continuation
继续执行的协程
bool is_cancelled() const noexcept
检查是否已取消
suspend_always initial_suspend() noexcept
初始暂停点
exception_ptr exception
异常指针