how-to-use/cpp/coroutine.cpp

141 lines
3.7 KiB
C++
Raw Permalink Normal View History

2024-05-01 14:39:10 +08:00
#include <iostream>
#include <coroutine>
//���ſ���
//1.Э����Ҫ�����첽�������̡�
//2.Э�̱���������ͨ�������û���û���𣬲�ͬ�ĵط���Э��״̬���ڶ��Ϸ��������ǵ���ջ������������ʱ��ͣ������ִ�еĹ��ܡ�
//3.�������ڳ�����co_await��co_return��co_yield����һ������������Ϊ�ú�����Э�̺�����
//��ʹ�á�
//1.Э�飺Э�̺����������з���ֵ��
//2.Э�飺�������ͱ�����Ƕ promise_type ���͡�
//3.Э�飺��Ƕ�� promise_type ����ʵ�����ټ����ض���
// A.initial_suspend
// B.final_suspend
// C.unhandled_exception
// D.get_return_object
//4.���ã�co_return ����Э�̺����ķ���
// �������� void ����Ƕ�� promise_type ������ʵ��
// E.return_void
// ��������ֵ���� ����Ƕ�� promise_type ������ʵ��
// F.return_value(T&& t) noexcept
//5.���ã�co_yield ��ʵ�� co_await �ı�����
// co_yield exp --> co_await promise.yield_value(exp)
// co_yield ����Э��ͬʱ����һ��ֵ����Ƕ�� promise_type ������ʵ��
// G.yield_value
//6.���ã�co_await exp �����ܵõ�һ�� awaitable ������
// �������������ض�ʵ�ֵľ��� awaitable ������
// A.bool await_ready
// B.T await_resume
// C.void await_suspend(std::coroutine_handle<> handle)
//��������
// 1.���ȵ��� await_ready��������ֵ��
// 2. false --> ���� await_suspend ����Э�̣��β� handle ��ʾЭ�̶��󣬿�����������Э�̡�
// true --> ���� await_resume ����ֵ��
// 3.��2���У��� false ����֮�󣬿��Ե��� await_resume
template<typename T>
struct SimpleGenerator
{
struct promise_type;
using coroutine_handle = std::coroutine_handle<promise_type>;
// ��������״̬
enum class State { Ready, Done };
// ��������promise����
struct promise_type {
T value{};
State state = State::Ready;
//��Э�̿�ʼ��ʱ������
auto initial_suspend() const noexcept {
return std::suspend_always{};
}
//��Э�̽�����ʱ������
auto final_suspend() const noexcept {
return std::suspend_always{};
}
SimpleGenerator get_return_object() {
return SimpleGenerator{ coroutine_handle::from_promise(*this) };
}
void return_void() {}
auto yield_value(T val) noexcept {
value = val;
state = State::Ready;
return std::suspend_always{};
}
void unhandled_exception() {
std::terminate();
}
};
// ���캯��
SimpleGenerator(coroutine_handle handle) : coro(handle) {}
// ��ֹ�������ƶ�
SimpleGenerator(const SimpleGenerator&) = delete;
SimpleGenerator& operator=(const SimpleGenerator&) = delete;
SimpleGenerator(SimpleGenerator&& other) noexcept : coro(other.coro) {
other.coro = nullptr;
}
SimpleGenerator& operator=(SimpleGenerator&& other) noexcept {
if (this != &other) {
coro = other.coro;
other.coro = nullptr;
}
return *this;
}
// ��������
~SimpleGenerator() {
if (coro)
coro.destroy();
}
// �����������Ƿ�����
bool done() const {
return coro && coro.done();
}
// ����������*���Ի�ȡ��ǰ��������ֵ
T& operator*() {
return coro.promise().value;
}
// ����++���������Լ�����������ִ��
void operator++() {
if (!done())
coro.resume();
}
private:
coroutine_handle coro;
};
// һ���򵥵�����������
SimpleGenerator<int> Counter(int start, int end) {
for (int i = start; i <= end; ++i) {
co_yield i;
}
}
int main() {
auto gen = Counter(1, 5);
while (!gen.done()) {
std::cout << *gen << std::endl;
++gen;
}
return 0;
}