1. Vấn đề nó giải quyết
Coroutine có thể suspend trong khi giữ local state rồi resume sau; ba keyword diễn đạt chờ, yield và hoàn tất. Nó làm một giả định quan trọng trở nên rõ và có thể kiểm tra.
2. Kiến thức cần có
Hàm, state machine, RAII và template cơ bản.
Bạn cần biết biên dịch chương trình ngắn và đọc output.
3. Ý tưởng cốt lõi
Compiler viết lại hàm thành resumable state machine nằm trong coroutine frame. Mỗi suspension là một dấu trang. Hãy đọc co_yield như lời hứa chính xác; runtime precondition vẫn do lập trình viên chịu trách nhiệm.
4. Cú pháp tối thiểu
co_await awaitable;
co_yield value;
co_return;5. Cách nó hoạt động
Chương trình đưa vào dạng nhỏ nhất cần thiết của
co_yield.Nó áp dụng tính năng lên dữ liệu cố định và giữ owner cần thiết trong scope.
Nó in một kết quả để đối chiếu trực tiếp với source.
6. Lỗi thường gặp
Keyword tự nó không cung cấp scheduling, thread hay ownership; return type và promise quyết định hành vi frame cùng cleanup.
Hãy kiểm tra cả header, mức hỗ trợ thư viện C++20, lifetime và kiểu được suy luận.
7. Khi nào nên dùng
Nên dùng khi computation tự nhiên pause/resume, sinh sequence hoặc chờ external completion.
Tránh dùng khi hàm hoặc loop thường diễn đạt control flow đơn giản hơn.
8. Ví dụ đơn giản
Generator tối thiểu dùng co_await suspend_never, yield hai giá trị rồi đến co_return; wrapper hủy frame. Tệp .cpp không nhận input nên kết quả dễ lặp lại.
Mã mẫu hoàn chỉnh
Tệp mã nguồn
cpp20/44_coroutine_model_keywords/main.cpp
// Day 44: Coroutine Model: co_await, co_yield, and co_return
#include <coroutine>
#include <exception>
#include <iostream>
#include <utility>
struct Generator {
struct promise_type;
using Handle = std::coroutine_handle<promise_type>;
struct promise_type {
int current{};
Generator get_return_object() { return Generator{Handle::from_promise(*this)}; }
std::suspend_always initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
std::suspend_always yield_value(int value) noexcept { current = value; return {}; }
void return_void() noexcept {}
void unhandled_exception() { std::terminate(); }
};
Handle handle{};
explicit Generator(Handle value) : handle{value} {}
Generator(Generator&& other) noexcept : handle{std::exchange(other.handle, {})} {}
Generator(const Generator&) = delete;
~Generator() { if (handle) handle.destroy(); }
bool next() { handle.resume(); return !handle.done(); }
int value() const { return handle.promise().current; }
};
Generator sequence() {
co_await std::suspend_never{};
co_yield 1;
co_yield 2;
co_return;
}
int main() {
auto values = sequence();
while (values.next()) std::cout << values.value() << ' ';
std::cout << '\n';
}
9. Điều cần nhớ
co_yielddiễn đạt ý tưởng C++20 trung tâm của ngày này.Ví dụ cô lập một hành vi bằng dữ liệu cố định.
Compiler check không thay thế suy luận về lifetime và runtime.
Ưu tiên interface nhỏ nhất nói đúng yêu cầu thật.
10. Câu hỏi tự kiểm tra
Dễ — Nhiệm vụ chính của
co_yieldtrong ví dụ tối thiểu là gì?Trung bình — Caller lấy lại quyền điều khiển ở statement nào sau khi yêu cầu generated value đầu?
Khó — Vì sao hai coroutine return type có thể diễn giải cùng cú pháp
co_returnkhác nhau?