全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

c++如何实现一个简单的协程库_c++ Boost.Context与ucontext【源码】

协程本质是控制流的主动挂起与恢复,需栈、寄存器上下文和调度逻辑;ucontext.h仅用于教学演示,Boost.Context提供跨平台、异常安全的工业级实现,C++20协程则为无栈状态机方案。

用 C++ 实现一个“简单”的协程库,核心不是从零造轮子(比如手写汇编切换栈),而是理解协程的本质:**控制流的主动挂起与恢复**,并借助系统或标准库提供的上下文切换原语。Boost.Context 是成熟方案,而 ucontext.h(POSIX)是更底层、可教学但已废弃的接口。下面直击重点,不绕弯。

一、协程的本质:栈 + 寄存器上下文 + 调度逻辑

协程不是线程,它不抢占、不依赖内核调度。一次协程切换 = 保存当前函数执行现场(栈指针、指令指针、通用寄存器等)→ 跳转到另一段栈上的函数继续执行。关键不在“多任务”,而在“可控让出”(yield)和“可控唤醒”(resume)。

所以真正要实现的最小闭环是:

  • 一个能分配独立栈内存的对象(如 char stack[8192]
  • 一套能保存/恢复 CPU 上下文的机制(这就是 ucontextboost::context::continuation 干的事)
  • 一个状态机管理协程生命周期(created → ready → running → suspended → done)

二、用 ucontext.h 写一个极简协程(仅作原理演示)

注意:ucontext 已被 POSIX 标准弃用,glibc 2.26+ 默认禁用,仅用于理解底层。生产环境请用 Boost.Context 或 C++20 协程。

下面是去掉错误检查、仅保留主干的可运行片段:

#include 
#include 
#include 

struct SimpleCoro { ucontext_t ctx; char stack[8192]; bool is_done = false;

SimpleCoro(std::function f) {
    getcontext(&ctx);
    ctx.uc_stack.ss_sp = stack;
    ctx.uc_stack.ss_size = sizeof(stack);
    ctx.uc_link = nullptr; // 挂起后返回到哪?这里设为 null,由我们手动 resume 控制
    makecontext(&ctx, [](int) {
        // 这里是协程体入口,需转成 C 风格函数
        auto* self = reinterpret_cast(reinterpret_cast(&self) - sizeof(self));
        self->body();
    }, 1, reinterpret_cast(&this));
}

void body() {
    // 用户逻辑在此运行
    std::cout << "coro running\n";
    // 模拟 yield:切回主协程(需提前保存主 ctx)
    swapcontext(&ctx, &main_ctx); // ⚠️ main_ctx 需在 main 中 setcontext 前 getcontext
    std::cout << "coro resumed\n";
    is_done = true;
}

void resume() {
    if (!is_done) swapcontext(&main_ctx, &ctx);
}

};

ucontext_t main_ctx; // 全局保存主上下文(不推荐,仅示意)

int main() { getcontext(&main_ctx); SimpleCoro c([]{}); c.resume(); // 启动协程 std::cout

⚠️ 缺陷明显:无法传递参数、无异常安全、栈大小固定、makecontext 参数传递靠 hack 地址、不可重入。这正是 Boost.Context 存在的理由。

三、用 Boost.Context 实现可工业使用的轻量协程

Boost.Context 封装了平台差异(x86/x64/ARM,Windows Fibers / Linux setjmp / macOS),提供 RAII、异常传播、栈分配策略。最简可用示例:

#include 
#include 

namespace ctx = boost::context;

struct Task { ctx::continuation c; bool done = false;

Task(std::function fn)
    : c_(ctx::callcc([fn = std::move(fn)](ctx::continuation&& c) {
          fn(c); // 用户函数接收 continuation,可用来 yield
          return std::move(c);
      })) {}

void resume() {
    if (!done_) c_ = std::move(c_).resume();
    done_ = c_.fpc_ == nullptr; // 判断是否已结束(内部指针为空)
}

void yield() {
    c_ = std::move(c_).resume(); // 切回父协程(即构造时 callcc 的调用方)
}

};

// 使用示例 int main() { Task t([](ctx::continuation& c) { std::cout

std::cout << "before first resume\n";
t.resume(); // 启动
std::cout << "after first resume\n";
t.resume(); // 继续

}

优势一目了然:

  • continuation 是移动语义安全的对象,支持栈上/堆上分配
  • callcc(call-with-current-continuation)天然支持双向跳转
  • 可指定栈大小、栈分配器(如 fixedsize_stackprotected_fixedsize_stack
  • 异常会正常传播(不像 ucontext 可能崩溃)

四、为什么不直接手写汇编?以及 C++20 协程怎么选?

手写汇编(如 x86 的 push/pop 所有寄存器 + 修改 rsp/rip)理论上可行,但:

  • 不同 ABI(System V / Win64)、不同架构(x86-64 / AArch64)寄存器列表和调用约定完全不同
  • 编译器优化(如 RVO、尾调用)可能破坏你预设的栈帧布局
  • 调试困难、无法和现代 C++ 特性(RAII、异常、lambda 捕获)自然融合

C++20 协程是语言级支持,语法简洁(co_await, co_yield, co_return),但它是无栈协程(stackless),依赖编译器生成状态机,不能像 Boost.Context 那样自由跳转任意函数。适合 I/O 等待场景,不适合需要完整调用栈的协作式多任务(如游戏逻辑帧、解释器)。

结论:学原理看 ucontext;做项目用 Boost.Context;新项目且场景匹配,优先评估 C++20 coroutines + libunifexcppcoro

基本上就这些。协程不神秘,难的是跨平台健壮性和与现代 C++ 生态的无缝集成——Boost.Context 已经替你扛住了。


# c++  # linux  # windows  # mac  #   # ai  # ios  # macos  # win  # stream  # cos  # 标准库  # 架构  # 封装  # char  # int  # Lambda  # 指针  # 接口  #   # 线程  # 对象  # 挂起  # 跳转  # 的是  # 闭环  # 在此  # 这就是  # 已被  # 设为  # 而在  # 是从 


相关文章: 建站之星收费标准详解:套餐费用及年费价格表一览  建站之星代理平台如何选择最佳方案?  网站专业制作公司,网站编辑是做什么的?好做吗?工作前景如何?  表情包在线制作网站免费,表情包怎么弄?  建站之星安装提示数据库无法连接如何解决?  高端智能建站公司优选:品牌定制与SEO优化一站式服务  建站主机空间推荐 高性价比配置与快速部署方案解析  制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?  免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?  如何处理“XML格式不正确”错误 常见XML well-formed问题解决方法  安云自助建站系统如何快速提升SEO排名?  较简单的网站制作软件有哪些,手机版网页制作用什么软件?  北京制作网站的公司排名,北京三快科技有限公司是做什么?北京三快科技?  佛山企业网站制作公司有哪些,沟通100网上服务官网?  制作网站的公司有哪些,做一个公司网站要多少钱?  如何在万网自助建站中设置域名及备案?  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  如何用低价快速搭建高质量网站?  如何高效利用亚马逊云主机搭建企业网站?  JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)  如何在阿里云虚拟主机上快速搭建个人网站?  如何快速选择适合个人网站的云服务器配置?  免费ppt制作网站,有没有值得推荐的免费PPT网站?  c# 在高并发下使用反射发射(Reflection.Emit)的性能  如何通过商城自助建站源码实现零基础高效建站?  建站之星上传入口如何快速找到?  C++如何使用std::optional?(处理可选值)  建站之星代理商如何保障技术支持与售后服务?  大同网页,大同瑞慈医院官网?  广州商城建站系统开发成本与周期如何控制?  如何快速生成可下载的建站源码工具?  实例解析Array和String方法  如何在阿里云通过域名搭建网站?  专业制作网站的公司哪家好,建立一个公司网站的费用.有哪些部分,分别要多少钱?  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  成都响应式网站开发,dw怎么把手机适应页面变成网页?  如何通过IIS搭建网站并配置访问权限?  如何快速启动建站代理加盟业务?  制作国外网站的软件,国外有哪些比较优质的网站推荐?  广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?  招贴海报怎么做,什么是海报招贴?  定制建站模板如何实现SEO优化与智能系统配置?18字教程  南平网站制作公司,2025年南平市事业单位报名时间?  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  建站之星导航菜单设置与功能模块配置全攻略  如何选择适合PHP云建站的开源框架?  电脑免费海报制作网站推荐,招聘海报哪个网站多?  微信h5制作网站有哪些,免费微信H5页面制作工具?  美食网站链接制作教程视频,哪个教做美食的网站比较专业点? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。