背景
协程句柄像指针一样可复制,却通常只应有一个销毁者。包装句柄的对象必须明确移动、完成和销毁的责任。
核心判断
- 禁止默认复制拥有型句柄,移动后源句柄清空。
- 规定谁负责 resume、何时等待完成、何时 destroy。
- promise 的 final_suspend 行为与拥有模型保持一致。
最小示例
下面保留核心逻辑;业务类型、调用入口和环境配置按项目补齐。
struct Task {
std::coroutine_handle<> h{};
explicit Task(std::coroutine_handle<> handle) : h(handle) {}
Task(const Task&) = delete;
Task& operator=(const Task&) = delete;
Task(Task&& other) noexcept : h(std::exchange(other.h, {})) {}
Task& operator=(Task&&) = delete;
// 前提:没有其他线程执行该协程,frame 未自销毁。
~Task() { if (h) h.destroy(); }
};
边界与误区
示例仅展示拥有型包装,假定 frame 保留在挂起状态并由包装器销毁。协程仍在别的线程执行时 destroy 不安全;自销毁 frame 也不能再次销毁。
验证方式
测试空句柄、移动构造、异常与正常完成路径,使用 sanitizer 检查 use-after-free。多线程调度需要额外同步,不能靠句柄包装自动获得安全。
小结
明确 coroutine handle 的拥有者、destroy 时机、异常传播和参数生命周期。