zoukankan      html  css  js  c++  java
  • 基于Duff's Device的C简易无栈协程实现

    参考 Simon Tatham 的文章https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

    译文为https://mthli.xyz/coroutines-in-c/

    协程是一组序列化的子过程,与线程不同,协程的调度是由用户而非操作系统执行的,协程可以在任意时刻让出CPU(称为yield操作),下次调用时从上次yield的地方继续执行

    Simon Tatham利用Duff's Device实现了一种简易的无栈协程,示例代码如下:

    int function(void) {
        static int i, state = 0;
        switch (state) {
            case 0: 
            for (i = 0; i < 10; i++) {
                state = 1; 
                return i;
                case 1:;
            }
        }
    } 
    

    该函数的作用是第i次调用时返回i,最多10次(相同的函数功能可以通过一个statci变量实现,但本文是为了讨论协程),其核心部分为switch语句以及return前后两句,通过设置不同的state来保证下一次调用时从上次退出的地方继续执行(如果不明白switch为何能和for套在一起写可以自行搜索Duff's Device)

    可以看出,每次调用return时设置的state必须不同,可以利用__LINE__宏来设置state,这样只要不在一行调用两次return即可

    以下是将其用宏封装的代码

    #include <stdio.h>
    
    #define crBegin static int state = 0; switch (state) { case 0:
    #define crReturn(x) do { state = __LINE__; return x; case __LINE__:; } while (0)
    #define crFinish }
    
    void f1() {
        crBegin;
        puts("1");
        puts("2");
        crReturn();
        puts("3");
        crFinish;
    }
    
    void f2() {
        crBegin;
        puts("x");
        crReturn();
        puts("y");
        puts("z");
        crFinish;
    }
    
    int main (void) {
        f1();
        f2();
        f1();
        f2();
        return 0;
    } 
    

    do while(0)是为了让crReturn与if else嵌套时不用考虑大括号问题

    这份代码运行后会依次输出1,2,x,3,y,z

    至此,一份用C实现的简易无栈协程就完成了,需要注意的是,因为switch内部不能任意定义变量,请在crBegin之前定义所需变量

    PS:这份代码仅供学习参考,如果你在实际生产代码中用了可能会被上司打死

  • 相关阅读:
    移动端注意
    每日日报
    每日日报
    每日日报
    每日日报
    每日日报
    每日日报
    每日日报
    每日日报
    每日日报
  • 原文地址:https://www.cnblogs.com/tusikalanse/p/13860751.html
Copyright © 2011-2022 走看看