0

0

c++怎么实现一个简单的协程库_c++手写协程实现原理与示例

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-11-10 14:08:02

|

227人浏览过

|

来源于php中文网

原创

协程通过用户态上下文切换实现轻量级并发,本文基于C++11和ucontext库实现简易协程,展示创建、挂起与恢复机制,利用getcontext、makecontext和swapcontext完成栈隔离与执行流控制,两个协程可交替执行,体现协程核心原理。

c++怎么实现一个简单的协程库_c++手写协程实现原理与示例

协程是一种比线程更轻量的并发编程模型,能够在用户态实现函数的暂停与恢复。C++20 引入了原生协程支持,但理解如何从零实现一个简单的协程库,有助于深入掌握其底层机制。下面介绍基于 C++11+ 的手写协程实现原理,并给出一个简易示例。

协程的基本概念

协程允许函数执行到某一点时暂停,保存当前状态,之后从中断处继续执行。它不同于线程,不依赖操作系统调度,开销小,适合高并发场景。

一个最简协程需要具备:

  • 可挂起(suspend)和恢复(resume)的能力
  • 上下文切换(context switch)机制
  • 状态管理(如是否完成、返回值等)

使用 ucontext 实现上下文切换

注意:ucontext 是 POSIX 标准的一部分,在 macOS 和 Linux 上可用,Windows 不支持。

我们可以借助 getcontextsetcontextmakecontextswapcontext 来实现协程的跳转。

立即学习C++免费学习笔记(深入)”;

核心思路是:

  • 每个协程拥有独立的空间和上下文(ucontext_t)
  • 主函数启动协程时,通过 makecontext 创建执行环境
  • 协程运行中可通过 swapcontext 切回主函数或其他协程

简易协程库实现示例

下面是一个极简的协程实现,包含创建、切换与恢复功能:

Pi智能演示文档
Pi智能演示文档

领先的AI PPT生成工具

下载
#include 
#include 
#include 
#include 
#include 

class SimpleCoroutine {
private:
    static std::map coroutines;
    static int current_id;
    static ucontext_t main_context;

    ucontext_t ctx;
    char* stack;
    int id;
    bool is_done;

public:
    SimpleCoroutine(std::function func) {
        id = ++current_id;
        stack = new char[8192]; // 8KB 栈空间
        is_done = false;

        getcontext(&ctx);
        ctx.uc_stack.ss_sp = stack;
        ctx.uc_stack.ss_size = 8192;
        ctx.uc_link = &main_context; // 协程结束回到主上下文
        makecontext(&ctx, (void(*)())lambda_wrapper, 1, this);

        coroutines[id] = ctx;
    }

    ~SimpleCoroutine() {
        delete[] stack;
    }

    static void lambda_wrapper(SimpleCoroutine* self) {
        self->is_done = false;
        self->run();
        self->is_done = true;
    }

    void run() {
        // 模拟协程体
        std::cout << "协程 " << id << " 开始执行\n";
        yield(); // 第一次让出
        std::cout << "协程 " << id << " 继续执行\n";
        yield();
        std::cout << "协程 " << id << " 执行结束\n";
    }

    void resume() {
        if (is_done) return;
        swapcontext(&main_context, &coroutines[id]);
    }

    static void yield() {
        swapcontext(&coroutines[current_id], &main_context);
    }

    static void yield(int cid) {
        swapcontext(&coroutines[current_id], &main_context);
    }
};

// 静态成员定义
std::map SimpleCoroutine::coroutines;
int SimpleCoroutine::current_id = 0;
ucontext_t SimpleCoroutine::main_context;

使用示例

测试两个协程交替执行:

int main() {
    getcontext(&SimpleCoroutine::main_context);

    SimpleCoroutine co1([]{}); // lambda 只是为了占位,实际逻辑在 run 中
    SimpleCoroutine co2([]{});

    std::cout << "主函数启动协程1\n";
    co1.resume();

    std::cout << "主函数启动协程2\n";
    co2.resume();

    std::cout << "主函数再次恢复协程1\n";
    co1.resume();

    std::cout << "主函数再次恢复协程2\n";
    co2.resume();

    return 0;
}

输出结果大致为:

主函数启动协程1
协程 1 开始执行
主函数启动协程2
协程 2 开始执行
主函数再次恢复协程1
协程 1 继续执行
主函数再次恢复协程2
协程 2 继续执行

原理总结

这个简易协程库的核心在于:

  • 每个协程有自己的栈和上下文,通过 ucontext 系列函数管理
  • makecontext 将函数绑定到指定上下文和栈上
  • swapcontext 实现两个上下文之间的切换
  • 协程结束后自动返回主上下文(uc_link 设置)

虽然这只是一个玩具级实现,但它展示了协程的本质:控制流的主动让出与恢复。

基本上就这些。真实生产环境中的协程库(如 Boost.Context、libco)会处理更多细节:异常安全、内存对齐、跨平台兼容、调度器等。但对于理解原理,这个例子足够清晰。

相关专题

更多
switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

518

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

404

2024.03.13

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

369

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

563

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

472

2023.08.10

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

516

2023.07.26

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1051

2023.07.27

windows照片无法显示
windows照片无法显示

当我们尝试打开一张图片时,可能会出现一个错误提示,提示说"Windows照片查看器无法显示此图片,因为计算机上的可用内存不足",本专题为大家提供windows照片无法显示相关的文章,帮助大家解决该问题。

748

2023.08.01

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.4万人学习

Git 教程
Git 教程

共21课时 | 2.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号