五种C++链式异步任务实现方式:一用std::future/promise构建显式依赖链;二用实验性协程实现同步风格await链;三用原子变量与信号量手动编排零分配任务;四用boost::asio::strand串行化I/O任务;五用弱引用回调表构建动态DAG任务图。

一、基于 std::future 和 std::promise 构建链式异步任务
该方法利用 C++11 引入的标准异步设施,通过 promise 设置值、future 获取结果,并借助 shared_future 实现多消费者复用,从而在不依赖第三方库的前提下构建可串联的异步执行流。其核心在于将前一个任务的 future 作为后一个任务的输入依赖,形成显式的执行顺序约束。
1、定义模板函数 chain_then,接收一个 std::future
2、在内部创建 std::promise,并启动一个独立线程:等待输入 future 就绪后调用 callable,将其返回的 future::get() 结果或异常设置到 promise 中。
3、返回该 promise 关联的 future,供下一级链式调用消费。
立即学习“C++免费学习笔记(深入)”;
4、确保所有 lambda 捕获的资源为值拷贝或显式 move,避免悬空引用。
二、使用 std::experimental::coroutines(C++20 前沿实践)实现协程链式调度
该方案采用编译器支持的无栈协程(如 MSVC / Clang 的 __declspec(naked) 或 gcc 的扩展),绕过传统回调嵌套,以同步风格编写异步逻辑。每个协程挂起点自动注册续体,调度器按依赖关系依次恢复执行,天然支持 await 链式展开。
1、定义 task
2、实现 awaiter 类型,包含 await_ready、await_suspend、await_resume 三成员,在 await_suspend 中将 resume_handle 绑定至前序任务完成通知队列。
3、编写链式调用表达式:co_await task1() 后直接 co_await task2(),编译器自动生成状态机跳转逻辑。
4、使用 thread_local 调度器实例管理 awaiter 生命周期,防止跨线程析构异常。
三、基于信号量与原子状态机的手动任务编排模型
此方法完全规避标准库异步对象开销,通过 std::atomic
1、为每个任务节点分配唯一 id 并初始化其前置依赖计数(例如:taskB.depends_on = {taskA.id},则 taskB.wait_count = 1)。
2、每个任务执行前调用 semaphore.acquire(),仅当所有前置任务将对应信号量 release 后才得以进入。
3、任务体执行完毕后,遍历其后续依赖列表,对每个后续任务调用其关联信号量的 release() 操作。
4、使用 std::atomic_flag 测试并置位任务完成标志,防止重复触发下游节点。
四、采用 boost::asio::strand 封装异步操作序列
该方法借助 Boost.Asio 的串行化执行上下文,将多个异步操作绑定至同一 strand,确保回调按 post 顺序串行执行,虽非严格“链式数据流”,但可模拟任务依赖顺序,适用于 I/O 密集型异步流水线场景。
1、构造 io_context 实例及配套 strand 对象,所有任务均通过 strand.post() 提交。
2、前序任务完成时,构造一个包装了下一任务逻辑的 lambda,并通过 strand.post() 提交,形成隐式链式调用。
3、在 lambda 内部检查前置结果状态,若失败则提前终止链路,调用 error_handler。
4、使用 boost::asio::defer 替代 post 可延迟至当前 handler 返回后再调度,避免栈溢出风险。
五、基于 callback 注册表与弱引用回调管理的任务图模型
该方案将任务抽象为有向无环图(DAG)节点,每个节点持有 weak_ptr 指向其前置节点结果存储区,通过回调注册表统一管理触发关系,支持动态插入/移除边、运行时条件分支,适合复杂业务流程编排。
1、定义 node_base 类,含 std::vector<:function>> on_complete_callbacks 成员,用于存储下游待触发函数。
2、每个任务执行完成后遍历自身 on_complete_callbacks,逐个 invoke;每个回调函数内持有一个 weak_ptr
3、调用 link_to(other_node) 时,将当前节点的完成回调 push 到 other_node 的 on_complete_callbacks 中,并绑定捕获 this 的 weak_ptr。
4、在 result_store 析构时调用 clear_all_callbacks(),遍历所有已注册回调并置空其内部 weak_ptr,防止悬挂调用。


















