std::stop_callback是C++20中用于协作式取消的单次执行清理回调,在stop_token被request_stop()通知后立即执行;常用于线程池任务、异步I/O等需及时释放资源的场景。

std::stop_callback 是什么,它在什么场景下必须用
std::stop_callback 是 C++20 引入的、配合 std::stop_source 和 std::stop_token 实现协作式取消的关键工具。它不是“自动触发”的钩子,而是**在 stop_token 被通知(request_stop())后、且该 token 仍有效时,立即执行一次的清理回调**。常见于线程池任务、异步 I/O 等需及时释放句柄、关闭文件、解锁 mutex 的场景——尤其当任务被外部中断,而你无法保证当前执行点是否已进入临界区。
如何正确构造和持有 std::stop_callback
错误写法是把它声明为局部变量却不维持生命周期:std::stop_callback cb(token, []{ /* cleanup */ }); —— 函数返回即析构,回调永远不被执行。正确做法是:将其作为类成员、lambda 捕获到异步 lambda 中,或显式延长生存期。
- 若在函数内注册,必须确保
std::stop_callback对象存活到取消发生或任务结束,例如:用std::unique_ptr<:stop_callback></:stop_callback>或绑定到std::shared_ptr管理的对象上 - 若在协程或 async lambda 中使用,需捕获
[cb = std::stop_callback{token, ...}](C++20 支持直接初始化捕获),否则闭包可能先于回调析构 - 注意:同一个
std::stop_token可注册多个std::stop_callback,它们按注册顺序逆序执行(后注册的先执行),适合嵌套资源清理
std::stop_callback 构造时的常见陷阱
最常踩的坑是传入的 callable 捕获了即将被销毁的对象,或调用了可能抛异常的代码。标准规定:若回调抛异常,程序直接调用 std::terminate()。
- 避免在回调里调用可能抛异常的函数,如
std::vector::push_back、带异常规格的 IO 操作;改用noexcept清理逻辑,比如直接 close fd、delete raw pointer、unlock mutex - 不要捕获 this 指针并访问成员变量,除非你能 100% 确保对象生命周期长于回调执行——更安全的做法是捕获所需资源的副本(如
int fd、std::mutex* mtx) -
std::stop_callback构造失败(如内存不足)会抛std::bad_alloc,但这是构造时异常,不属于回调执行期异常,可被捕获
一个真实可用的资源封装示例
下面是一个封装文件描述符的 RAII 类,它在 stop_token 触发时自动 close:
class guarded_fd {
int fd_ = -1;
std::stop_callback cb_;
<p>public:
guarded_fd(int fd, std::stop<em>token stoken)
: fd</em>(fd), cb_(stoken, <a href="https://www.php.cn/link/3222698060b74229ab01f4b3d33f9b59">fd</a> {
if (fd != -1) ::close(fd); // noexcept, no throw
}) {}</p><pre class="brush:php;toolbar:false;">~guarded_fd() {
if (fd_ != -1) ::close(fd_);
fd_ = -1;
}
// move-only, disable copy
guarded_fd(guarded_fd&&) = default;
guarded_fd& operator=(guarded_fd&&) = default;};
关键点:回调捕获的是 fd 值而非 this,::close 是 noexcept 的,且析构函数仍兜底处理未被取消时的清理。如果 fd_ 是动态分配的资源(如 new 出来的 buffer),同样适用此模式。
真正容易被忽略的是:std::stop_callback 不提供取消“取消操作”本身的能力——一旦 request_stop() 被调用,所有已注册的回调必然执行(只要 token 有效且对象未销毁)。你要做的,只是确保回调体足够轻量、无异常、不依赖外部状态。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











