C++20中可用std::stop_source实现统一可传播的协作式取消机制:一、jthread自动绑定stop_token;二、显式共享token;三、协程中用自定义awaiter检查取消;四、stop_callback构建层级传播;五、结合condition_variable实现可取消等待。

如果您在 C++20 及以上环境中构建多线程协作任务系统,发现难以安全、及时地中断正在运行的异步操作链或嵌套协程调用,则可能是由于缺乏统一、可传播的取消信号机制。std::stop_source 提供了标准化的协作式取消原语,支持跨线程、跨协程传递停止请求。以下是实现该机制的多种具体方式:
一、基于 std::jthread 与隐式 stop_token 绑定
std::jthread 在构造时自动关联一个 std::stop_source,并将其 stop_token 传递给启动的函数;线程函数可通过检查 token 状态决定是否提前退出,且在线程析构时自动请求停止,确保资源清理时机可控。
1、定义接收 stop_token 的可调用对象,例如 lambda 或函数对象,在内部定期调用 token.stop_requested() 判断是否应终止。
2、将该可调用对象传入 std::jthread 构造函数,无需手动管理 stop_source 生命周期。
立即学习“C++免费学习笔记(深入)”;
3、在需要提前终止时,调用 jthread 对象的 request_stop() 成员函数,触发所有绑定 token 的检查点响应。
二、显式创建 stop_source 并共享 stop_token
当任务结构跨越多个独立线程、协程或需细粒度控制取消传播路径时,可手动构造 std::stop_source,并通过值传递或引用传递其 stop_token 给各协作单元;每个单元持有一个只读视图,仅能观察状态,不能发起请求,从而保障取消权限集中管控。
1、在任务调度器或根协程作用域中声明 std::stop_source source;。
2、将 source.get_token() 的返回值分别传入子任务函数、std::thread 构造参数、或 co_await 表达式中使用的自定义 awaitable。
3、各子任务在循环体头部或关键等待点插入 if (token.stop_requested()) return; 或 throw std::stop_token::stop_requested();。
三、在协程中结合 co_await 实现可取消挂起
通过自定义可等待类型包装 stop_token,使协程能在挂起前主动检查取消状态;若已请求停止,则跳过挂起直接返回,避免陷入不可中断的等待状态,提升响应实时性。
1、定义 struct stop_awaiter { std::stop_token token; bool await_ready() const noexcept { return token.stop_requested(); } void await_suspend(std::coroutine_handle) const noexcept {} void await_resume() const noexcept {} };。
2、在协程函数体内执行 co_await stop_awaiter{token};,该表达式在 token 已被请求时立即完成,否则不挂起。
3、将此模式嵌入 I/O 等待逻辑前,例如在调用 recv 或 sleep_for 前插入该 co_await,形成“检查-挂起”原子节拍。
四、组合多个 stop_token 实现层级化取消传播
使用 std::stop_callback 将子任务的停止请求转发至父级 stop_source,构建树状取消传播链;任一子节点请求停止,均可触发上游节点的响应逻辑,适用于分阶段任务或依赖拓扑明确的协作模型。
1、为每个子任务分配独立的 std::stop_source sub_source;。
2、在父任务中注册回调:std::stop_callback callback{parent_source.get_token(), [&sub_source]() { sub_source.request_stop(); }};
3、子任务在其自身逻辑中调用 sub_source.request_stop() 时,自动触发父级回调,进而通知 parent_source 所有其他监听者。
五、与 std::condition_variable 配合实现带取消的等待
标准 condition_variable::wait 阻塞调用无法响应外部取消信号,必须包裹在循环中并每次检查 stop_token;通过将 token 检查与 predicate 判断合并,确保等待过程具备协作中断能力,避免死锁或永久阻塞。
1、将 std::unique_lock 与 std::stop_token 同时捕获进 wait 的 lambda predicate 中。
2、predicate 返回 true 仅当条件满足 且 token.stop_requested() 为 false;若为 true,则 wait 立即返回,后续逻辑可执行清理并退出。
3、在 wait 返回后,显式检查 token.stop_requested(),若为真则抛出异常或返回错误码,中断当前任务流。


















