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
14
16#ifdef NEFORCE_STANDARD_20
22NEFORCE_BEGIN_NAMESPACE__
23
28
37public:
46
51 NEFORCE_NODISCARD bool await_ready() const noexcept { return token != nullptr && token->is_cancelled(); }
52
57 void await_suspend(coroutine_handle<> h) const noexcept {}
58
63 void await_resume() const {
64 if (token != nullptr && token->is_cancelled()) {
65 NEFORCE_THROW_EXCEPTION(exception("Operation cancelled"));
66 }
67 }
68 };
69
70private:
71 struct state {
72 atomic<bool> cancelled{false};
73 atomic<size_t> ref_count{1};
74 };
75 state* state_;
76
80 void release() {
81 if (state_ != nullptr && state_->ref_count.fetch_sub(1, memory_order_acq_rel) == 1) {
82 delete state_;
83 }
84 }
85
86public:
91 state_(new state()) {}
92
98 state_(other.state_) {
99 if (state_ != nullptr) {
100 state_->ref_count.fetch_add(1, memory_order_relaxed);
101 }
102 }
103
110 if (addressof(other) == this) {
111 return *this;
112 }
113
114 release();
115 state_ = other.state_;
116 if (state_ != nullptr) {
117 state_->ref_count.fetch_add(1, memory_order_relaxed);
118 }
119 return *this;
120 }
121
125 ~cancellation_token() { release(); }
126
130 void cancel() noexcept {
131 if (state_ != nullptr) {
132 state_->cancelled.store(true, memory_order_release);
133 }
134 }
135
140 NEFORCE_NODISCARD bool is_cancelled() const noexcept {
141 return state_ != nullptr && state_->cancelled.load(memory_order_acquire);
142 }
143
148 NEFORCE_NODISCARD check_awaiter check() const { return check_awaiter{this}; }
149};
150
151
152template <typename T>
153class generator;
154
156NEFORCE_BEGIN_INNER__
157
158template <typename T, typename F>
159generator<invoke_result_t<F, T>> generator_map(generator<T> source, F func);
160
161template <typename T, typename Pred>
162generator<T> generator_filter(generator<T> source, Pred pred);
163
164template <typename T>
165generator<T> generator_take(generator<T> source, size_t n);
166
167template <typename T>
168generator<T> generator_skip(generator<T> source, size_t n);
169
170template <typename T>
171generator<T> generator_chain(generator<T> source, generator<T> other);
172
173NEFORCE_END_INNER__
175
176
185template <typename T>
187public:
195
201
206 suspend_always initial_suspend() noexcept { return {}; }
207
212 suspend_always final_suspend() noexcept { return {}; }
213
220 current_value = _NEFORCE move(value);
221 return {};
222 }
223
227 void return_void() noexcept {}
228
233 };
234
239 struct iterator {
240 using iterator_category = input_iterator_tag;
241 using value_type = T;
242 using difference_type = ptrdiff_t;
243 using pointer = T*;
244 using reference = T&;
245
247
251 iterator() = default;
252
259
265 handle.resume();
266 if (handle.done()) {
267 handle = nullptr;
268 }
269 return *this;
270 }
271
275 void operator++(int) { ++(*this); }
276
281 T& operator*() const noexcept {
282 NEFORCE_CONSTEXPR_ASSERT(handle.promise().current_value.has_value());
283 return *handle.promise().current_value;
284 }
285
290 T* operator->() const noexcept { return &(*handle.promise().current_value); }
291
297 bool operator==(const iterator& other) const noexcept { return handle == other.handle; }
298
304 bool operator!=(const iterator& other) const noexcept { return !(*this == other); }
305 };
306
307private:
309
310public:
316 handle_(h) {}
317
322 generator(generator&& other) noexcept :
323 handle_(other.handle_) {
324 other.handle_ = nullptr;
325 }
326
332 generator& operator=(generator&& other) noexcept {
333 if (addressof(other) == this) {
334 return *this;
335 }
336
337 if (handle_) {
338 handle_.destroy();
339 }
340 handle_ = other.handle_;
341 other.handle_ = nullptr;
342
343 return *this;
344 }
345
350 if (handle_) {
351 handle_.destroy();
352 }
353 }
354
355 generator(const generator&) = delete;
356 generator& operator=(const generator&) = delete;
357
363 if (handle_) {
364 handle_.resume();
365 if (handle_.promise().exception) {
366 _NEFORCE rethrow_exception(handle_.promise().exception);
367 }
368 if (handle_.done()) {
369 return iterator{nullptr};
370 }
371 }
372 return iterator{handle_};
373 }
374
379 iterator end() { return iterator{nullptr}; }
380
387 template <typename F>
389 return inner::generator_map(move(*this), move(func));
390 }
391
398 template <typename Pred>
399 generator filter(Pred pred) {
400 return inner::generator_filter(move(*this), move(pred));
401 }
402
408 generator take(const size_t n) { return inner::generator_take(move(*this), n); }
409
415 generator skip(const size_t n) { return inner::generator_skip(move(*this), n); }
416
422 generator chain(generator other) { return inner::generator_chain(move(*this), move(other)); }
423
429 template <typename F>
430 void for_each(F&& func) {
431 for (auto&& value: *this) {
432 func(_NEFORCE forward<decltype(value)>(value));
433 }
434 }
435
444 template <typename Acc, typename F>
445 Acc fold(Acc init, F&& func) {
446 Acc result = _NEFORCE move(init);
447 for (auto&& value: *this) {
448 result = func(_NEFORCE move(result), _NEFORCE forward<decltype(value)>(value));
449 }
450 return result;
451 }
452};
453
454
456NEFORCE_BEGIN_INNER__
457
458template <typename T, typename F>
459generator<invoke_result_t<F, T>> generator_map(generator<T> source, F func) {
460 for (auto&& value: source) {
461 co_yield func(_NEFORCE forward<decltype(value)>(value));
462 }
463}
464
465template <typename T, typename Pred>
466generator<T> generator_filter(generator<T> source, Pred pred) {
467 for (auto&& value: source) {
468 if (pred(value)) {
469 co_yield _NEFORCE forward<decltype(value)>(value);
470 }
471 }
472}
473
474template <typename T>
475generator<T> generator_take(generator<T> source, size_t n) {
476 size_t count = 0;
477 for (auto&& value: source) {
478 if (count >= n) {
479 break;
480 }
481 co_yield _NEFORCE forward<decltype(value)>(value);
482 ++count;
483 }
484}
485
486template <typename T>
487generator<T> generator_skip(generator<T> source, size_t n) {
488 size_t count = 0;
489 for (auto&& value: source) {
490 if (count < n) {
491 ++count;
492 continue;
493 }
494 co_yield _NEFORCE forward<decltype(value)>(value);
495 }
496}
497
498template <typename T>
499generator<T> generator_chain(generator<T> source, generator<T> other) {
500 for (auto&& value: source) {
501 co_yield _NEFORCE forward<decltype(value)>(value);
502 }
503 for (auto&& value: other) {
504 co_yield _NEFORCE forward<decltype(value)>(value);
505 }
506}
507
508NEFORCE_END_INNER__
510
519template <typename T>
520class task {
521public:
536 bool await_ready() noexcept { return false; }
537
544 auto& promise = h.promise();
545 if (promise.continuation) {
546 promise.continuation.resume();
547 }
548 }
549
553 void await_resume() noexcept {}
554 };
555
556 using value_type = T;
557
562
568
574
579 NEFORCE_NODISCARD bool is_cancelled() const noexcept { return token != nullptr && token->is_cancelled(); }
580
585 suspend_always initial_suspend() noexcept { return {}; }
586
591 final_awaiter final_suspend() noexcept { return {}; }
592
597 void return_value(T value) { result = _NEFORCE move(value); }
598
603 };
604
609 struct awaiter {
611
616 NEFORCE_NODISCARD bool await_ready() const noexcept { return handle.done(); }
617
624 handle.promise().continuation = continuation;
625 return handle;
626 }
627
633 if (handle.promise().exception) {
634 _NEFORCE rethrow_exception(handle.promise().exception);
635 }
636 return _NEFORCE move(*handle.promise().result);
637 }
638 };
639
640private:
642
643public:
649 handle_(h) {}
650
655 task(task&& other) noexcept :
656 handle_(other.handle_) {
657 other.handle_ = nullptr;
658 }
659
665 task& operator=(task&& other) noexcept {
666 if (addressof(other) == this) {
667 return *this;
668 }
669
670 if (handle_) {
671 handle_.destroy();
672 }
673 handle_ = other.handle_;
674 other.handle_ = nullptr;
675
676 return *this;
677 }
678
683 if (handle_) {
684 handle_.destroy();
685 }
686 }
687
688 task(const task&) = delete;
689 task& operator=(const task&) = delete;
690
695 awaiter operator co_await() { return awaiter{handle_}; }
696
701 NEFORCE_NODISCARD bool done() const noexcept { return handle_.done(); }
702
706 void resume() {
707 if (handle_ && !handle_.done()) {
708 handle_.resume();
709 }
710 }
711
716 T get() {
717 while (!handle_.done()) {
718 handle_.resume();
719 }
720 if (handle_.promise().exception) {
721 _NEFORCE rethrow_exception(handle_.promise().exception);
722 }
723 return _NEFORCE move(*handle_.promise().result);
724 }
725
731 if (handle_) {
732 handle_.promise().set_cancellation_token(&token);
733 }
734 }
735
740 NEFORCE_NODISCARD bool is_cancelled() const noexcept { return handle_ && handle_.promise().is_cancelled(); }
741};
742
743
747template <>
748class task<void> {
749public:
750 struct promise_type {
751 using value_type = void;
752
755 cancellation_token* token = nullptr;
756
758
760
761 NEFORCE_NODISCARD bool is_cancelled() const { return token != nullptr && token->is_cancelled(); }
762
763 suspend_always initial_suspend() noexcept { return {}; }
764
765 struct final_awaiter {
766 bool await_ready() noexcept { return false; }
767
769 auto& promise = h.promise();
770 if (promise.continuation) {
771 promise.continuation.resume();
772 }
773 }
774
775 void await_resume() noexcept {}
776 };
777
778 final_awaiter final_suspend() noexcept { return {}; }
779
780 void return_void() noexcept {}
781
783 };
784
785 struct awaiter {
787
788 NEFORCE_NODISCARD bool await_ready() const noexcept { return handle.done(); }
789
791 handle.promise().continuation = continuation;
792 return handle;
793 }
794
795 void await_resume() {
796 if (handle.promise().exception) {
797 rethrow_exception(handle.promise().exception);
798 }
799 }
800 };
801
802private:
804
805public:
807 handle_(h) {}
808
809 task(task&& other) noexcept :
810 handle_(other.handle_) {
811 other.handle_ = nullptr;
812 }
813
814 task& operator=(task&& other) noexcept {
815 if (addressof(other) == this) {
816 return *this;
817 }
818
819 if (handle_) {
820 handle_.destroy();
821 }
822 handle_ = other.handle_;
823 other.handle_ = nullptr;
824
825 return *this;
826 }
827
828 ~task() {
829 if (handle_) {
830 handle_.destroy();
831 }
832 }
833
834 task(const task&) = delete;
835 task& operator=(const task&) = delete;
836
837 awaiter operator co_await() { return awaiter{handle_}; }
838
839 NEFORCE_NODISCARD bool done() const { return handle_.done(); }
840
841 void resume() {
842 if (handle_ && !handle_.done()) {
843 handle_.resume();
844 }
845 }
846
847 void get() {
848 while (!handle_.done()) {
849 handle_.resume();
850 }
851 if (handle_.promise().exception) {
852 rethrow_exception(handle_.promise().exception);
853 }
854 }
855
857 if (handle_) {
858 handle_.promise().set_cancellation_token(&token);
859 }
860 }
861
862 NEFORCE_NODISCARD bool is_cancelled() const { return handle_ && handle_.promise().is_cancelled(); }
863};
864
865
874template <typename... Tasks>
875auto when_all(Tasks... tasks) -> task<tuple<typename Tasks::promise_type::value_type...>> {
876 tuple<typename Tasks::promise_type::value_type...> results;
877 auto task_tuple = _NEFORCE make_tuple(_NEFORCE move(tasks)...);
878 [&]<size_t... Is>(index_sequence<Is...>) {
879 ((_NEFORCE get<Is>(results) = _NEFORCE get<Is>(task_tuple).get()), ...);
880 }(index_sequence_for<Tasks...>{});
881 co_return results;
882}
883
884
896template <typename T, typename Factory>
897task<T> retry(Factory factory, const size_t max_attempts,
898 const function<bool(const exception_ptr&)>& should_retry = {}) {
899 static_assert(_NEFORCE is_invocable_r_v<task<T>, Factory>, "Factory must return task<T>");
900
901 exception_ptr last_exception;
902
903 for (size_t attempt = 0; attempt < max_attempts; ++attempt) {
904 try {
905 co_return co_await factory();
906 } catch (...) {
907 last_exception = _NEFORCE current_exception();
908
909 if (should_retry && !should_retry(last_exception)) {
910 rethrow_exception(last_exception);
911 }
912 if (attempt == max_attempts - 1) {
913 rethrow_exception(last_exception);
914 }
915 }
916 }
917
918 rethrow_exception(last_exception);
919}
920 // Coroutine
922
923NEFORCE_END_NAMESPACE__
924#endif // NEFORCE_STANDARD_20
925#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 filter(Pred pred)
过滤
generator take(const size_t n)
取前n个元素
generator< invoke_result_t< F, T > > map(F func)
映射变换
generator & operator=(generator &&other) noexcept
移动赋值运算符
generator chain(generator other)
连接两个生成器
void for_each(F &&func)
遍历每个元素
iterator begin()
获取起始迭代器
generator(generator &&other) noexcept
移动构造函数
Acc fold(Acc init, F &&func)
折叠(归约)
~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)
从协程句柄构造
协程支持
异常指针实现
通用函数包装器
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr T * addressof(T &x) noexcept
获取对象的地址
enable_if_t< is_void_v< T >, future_result_t< T > > get(future< T > &f)
通用future结果获取函数
std::coroutine_handle< Promise > coroutine_handle
协程句柄
task< T > retry(Factory factory, const size_t max_attempts, const function< bool(const exception_ptr &)> &should_retry={})
带重试的异步操作
auto when_all(Tasks... tasks) -> task< tuple< typename Tasks::promise_type::value_type... > >
等待所有任务完成
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
#define NEFORCE_CONSTEXPR_ASSERT(COND)
编译时常量断言
NEFORCE_NORETURN void rethrow_exception(const exception_ptr &p)
重新抛出异常
exception_ptr current_exception() noexcept
获取当前异常
integer_sequence< size_t, Values... > index_sequence
索引序列
make_index_sequence< sizeof...(Types)> index_sequence_for
根据类型参数包生成索引序列
constexpr bool is_invocable_r_v
is_invocable_r的便捷变量模板
constexpr auto memory_order_release
释放内存顺序常量
constexpr auto memory_order_relaxed
宽松内存顺序常量
constexpr auto memory_order_acquire
获取内存顺序常量
constexpr auto memory_order_acq_rel
获取-释放内存顺序常量
int64_t ptrdiff_t
指针差类型
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
thread::native_handle_type handle() noexcept
获取当前线程句柄
constexpr tuple< unwrap_ref_decay_t< Types >... > make_tuple(Types &&... args)
从参数创建元组
可选值类型
通用原子类型模板
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
检查是否可立即恢复
void 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
继续执行的协程
T value_type
任务结果类型别名
bool is_cancelled() const noexcept
检查是否已取消
suspend_always initial_suspend() noexcept
初始暂停点
exception_ptr exception
异常指针
元组实现