1. Vấn đề nó giải quyết
Promise tùy chỉnh hành vi coroutine, handle điều khiển suspended frame, còn frame lưu state cần qua các lần suspension. 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ó
Mô hình coroutine state machine ở Ngày 44.
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
Promise là bảng điều khiển trong frame; handle là remote nhỏ có thể resume, inspect hoặc destroy frame đó. Hãy đọc std::coroutine_handle 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
using Handle = std::coroutine_handle<promise_type>;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
std::coroutine_handle.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
Raw handle không tự sở hữu cleanup; destroy hai lần, leak hoặc resume frame hoàn tất/dangling đều gây undefined behavior.
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 xây coroutine abstraction cần protocol lifecycle và result rõ ràng.
Tránh dùng khi task hoặc generator abstraction có sẵn đã cung cấp ownership an toàn.
8. Ví dụ đơn giản
Task move-only nhỏ lấy typed handle từ promise, resume một lần, đọc result và destroy frame trong destructor. 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/45_promise_handle_coroutine_frame/main.cpp
// Day 45: Promise Type, Coroutine Handle, and Coroutine Frame
#include <coroutine>
#include <iostream>
#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_always 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(); }
int run() { handle.resume(); return handle.promise().result; }
};
Task answer() {
co_return 42;
}
int main() {
Task task = answer();
std::cout << "result = " << task.run() << '\n';
}
9. Điều cần nhớ
std::coroutine_handlediễ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
std::coroutine_handletrong ví dụ tối thiểu là gì?Trung bình — Promise member nào tạo return object chứa handle?
Khó — Vì sao wrapper phải cấm copy khi destructor gọi
handle.destroy()?