### **C++20 协程(Coroutines)代码示例**

C++20 引入了协程(Coroutines),它是一种轻量级的用户态线程,可以在不阻塞线程的情况下暂停和恢复函数执行。协程特别适合 **异步I/O**、**生成器** 和 **状态机** 等场景。

---

## **1. 基本协程示例(生成器模式)**
协程通过 `co_yield` 暂停执行并返回值,通过 `co_return` 结束执行。

### **示例:生成整数序列**
```cpp
#include <iostream>
#include <coroutine>
#include <memory>

// 1. 定义协程返回类型
struct Generator {
    struct promise_type {
        int current_value;  // 当前生成的值

        // 协程开始时调用
        Generator get_return_object() {
            return Generator(std::coroutine_handle<promise_type>::from_promise(*this));
        }

        // 初始挂起点
        std::suspend_always initial_suspend() { return {}; }

        // 协程结束时挂起(避免自动销毁)
        std::suspend_always final_suspend() noexcept { return {}; }

        // 处理 co_yield
        std::suspend_always yield_value(int value) {
            current_value = value;
            return {};
        }

        // 处理 co_return
        void return_void() {}

        // 异常处理
        void unhandled_exception() { std::terminate(); }
    };

    // 协程句柄
    std::coroutine_handle<promise_type> coro;

    // 构造函数
    explicit Generator(std::coroutine_handle<promise_type> h) : coro(h) {}

    // 析构时销毁协程
    ~Generator() {
        if (coro) coro.destroy();
    }

    // 获取下一个值
    int next() {
        coro.resume();  // 恢复协程
        return coro.promise().current_value;
    }
};

// 2. 定义一个协程函数
Generator generateNumbers(int start, int end) {
    for (int i = start; i <= end; ++i) {
        co_yield i;  // 暂停并返回值
    }
    co_return;  // 结束协程
}

int main() {
    // 3. 使用协程
    Generator gen = generateNumbers(1, 5);

    // 逐个获取值
    std::cout << gen.next() << std::endl;  // 1
    std::cout << gen.next() << std::endl;  // 2
    std::cout << gen.next() << std::endl;  // 3
    std::cout << gen.next() << std::endl;  // 4
    std::cout << gen.next() << std::endl;  // 5

    return 0;
}
```
**输出**:
```
1
2
3
4
5
```

---

## **2. 异步任务(模拟 `std::future`)**
协程可以用于简化异步编程,模拟 `std::future` 的行为。

### **示例:异步计算**
```cpp
#include <iostream>
#include <coroutine>
#include <thread>
#include <chrono>

// 1. 定义异步任务类型
struct AsyncTask {
    struct promise_type {
        int result;  // 存储计算结果

        AsyncTask get_return_object() {
            return AsyncTask(std::coroutine_handle<promise_type>::from_promise(*this));
        }

        std::suspend_never initial_suspend() { return {}; }  // 立即执行
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_value(int value) { result = value; }  // co_return 返回值
        void unhandled_exception() { std::terminate(); }
    };

    std::coroutine_handle<promise_type> coro;

    explicit AsyncTask(std::coroutine_handle<promise_type> h) : coro(h) {}
    ~AsyncTask() { if (coro) coro.destroy(); }

    int get() {
        if (!coro.done()) {
            coro.resume();  // 恢复协程(如果未完成)
        }
        return coro.promise().result;
    }
};

// 2. 模拟耗时计算
AsyncTask computeAsync(int a, int b) {
    std::cout << "Starting async computation..." << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));  // 模拟耗时
    co_return a + b;  // 返回结果
}

int main() {
    // 3. 启动异步任务
    AsyncTask task = computeAsync(10, 20);

    std::cout << "Doing other work..." << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    // 获取结果(如果未完成,会等待)
    std::cout << "Result: " << task.get() << std::endl;  // 30

    return 0;
}
```
**输出**:
```
Starting async computation...
Doing other work...
Result: 30
```

---

## **3. 协程与事件循环(模拟异步I/O)**
协程可以与事件循环结合,实现非阻塞I/O操作。

### **示例:模拟异步文件读取**
```cpp
#include <iostream>
#include <coroutine>
#include <functional>

// 1. 定义异步操作
struct AsyncRead {
    struct promise_type {
        std::string data;  // 存储读取的数据

        AsyncRead get_return_object() {
            return AsyncRead(std::coroutine_handle<promise_type>::from_promise(*this));
        }

        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_value(std::string value) { data = value; }
        void unhandled_exception() { std::terminate(); }
    };

    std::coroutine_handle<promise_type> coro;

    explicit AsyncRead(std::coroutine_handle<promise_type> h) : coro(h) {}
    ~AsyncRead() { if (coro) coro.destroy(); }

    std::string get() {
        if (!coro.done()) coro.resume();
        return coro.promise().data;
    }
};

// 2. 模拟异步读取
AsyncRead readFileAsync() {
    std::cout << "Start reading file..." << std::endl;
    co_await std::suspend_always{};  // 模拟异步挂起
    std::cout << "File read complete!" << std::endl;
    co_return "File content: Hello, Coroutines!";
}

int main() {
    AsyncRead reader = readFileAsync();

    std::cout << "Doing other work..." << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    std::cout << reader.get() << std::endl;  // 获取文件内容

    return 0;
}
```
**输出**:
```
Start reading file...
Doing other work...
File read complete!
File content: Hello, Coroutines!
```

---

## **4. 协程的底层控制(手动调度)**
可以通过自定义 `Awaiter` 控制协程的挂起和恢复逻辑。

### **示例:自定义 `Awaiter`**
```cpp
#include <iostream>
#include <coroutine>

struct MyAwaiter {
    bool await_ready() const noexcept { return false; }  // 总是挂起
    void await_suspend(std::coroutine_handle<> h) const {
        std::cout << "Suspended coroutine!" << std::endl;
        h.resume();  // 立即恢复
    }
    void await_resume() const noexcept {
        std::cout << "Resumed coroutine!" << std::endl;
    }
};

struct Task {
    struct promise_type {
        Task get_return_object() { return {}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() { std::terminate(); }
    };
};

Task myCoroutine() {
    std::cout << "Before await" << std::endl;
    co_await MyAwaiter{};  // 自定义挂起/恢复逻辑
    std::cout << "After await" << std::endl;
}

int main() {
    myCoroutine();
    return 0;
}
```
**输出**:
```
Before await
Suspended coroutine!
Resumed coroutine!
After await
```

---

## **总结**
| 场景               | 关键 API                | 用途                          |
|--------------------|-------------------------|-------------------------------|
| **生成器**         | `co_yield`              | 惰性生成序列(如 `range`)     |
| **异步任务**       | `co_return` + `co_await`| 简化 `std::future` 风格代码    |
| **事件驱动 I/O**   | 自定义 `Awaiter`        | 非阻塞操作(如网络请求)       |
| **手动调度**       | `std::coroutine_handle` | 低级别协程控制                |

**编译器支持**:
- GCC 10+ (`-fcoroutines`)
- Clang 12+ (`-fcoroutines-ts`)
- MSVC 2019+ (`/await`)

协程是 C++20 的重要特性,适合 **异步编程** 和 **生成器模式**,但需要一定的学习成本。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐