1. Vấn đề nó giải quyết
Coroutine task biểu diễn operation có thể pause rồi cung cấp một result hoặc exception cho continuation sau. 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ó
Awaiter, task result, handle và scheduling boundary.
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
Task là biên nhận cho công việc chưa xong. co_await đăng ký điểm tiếp tục, còn scheduler hoặc event source cuối cùng resume frame. Hãy đọc co_await 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
int value = co_await operation;
co_return value;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_await.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
Coroutine không tự động parallel hay asynchronous; thiếu scheduler thật, awaiter có thể chỉ mô phỏng suspension point.
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 code nhìn tuần tự cần phối hợp completion bất đồng bộ thật.
Tránh dùng khi công việc có ngay, CPU-bound không scheduler hoặc plain future đã đủ.
8. Ví dụ đơn giản
Task nhỏ suspend một lần, được main resume thủ công rồi trả integer cố định qua promise. 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/48_asynchronous_coroutine_task/main.cpp
// Day 48: Asynchronous Tasks with Coroutines
#include <coroutine>
#include <iostream>
#include <stdexcept>
#include <utility>
struct Task {
struct promise_type;
using Handle = std::coroutine_handle<promise_type>;
struct promise_type {
int result{};
Task get_return_object() { return Task{Handle::from_promise(*this)}; }
std::suspend_never initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_value(int value) noexcept { result = value; }
void unhandled_exception() { std::terminate(); }
};
Handle handle{};
explicit Task(Handle value) : handle{value} {}
Task(Task&& other) noexcept : handle{std::exchange(other.handle, {})} {}
Task(const Task&) = delete;
~Task() { if (handle) handle.destroy(); }
void resume() { handle.resume(); }
bool done() const { return handle.done(); }
int value() const { if (!done()) throw std::logic_error("not ready"); return handle.promise().result; }
};
Task async_value() {
co_await std::suspend_always{}; // Educational scheduling boundary.
co_return 42;
}
int main() {
Task task = async_value();
std::cout << "ready before resume = " << std::boolalpha << task.done() << '\n';
task.resume();
std::cout << "result = " << task.value() << '\n';
}
9. Điều cần nhớ
co_awaitdiễ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_awaittrong ví dụ tối thiểu là gì?Trung bình — Vì sao result chưa có trước khi caller resume suspended task?
Khó — Thành phần nào còn thiếu khiến ví dụ giáo dục này chưa thực hiện background I/O thật?