前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C/C++协程的简单尝试

C/C++协程的简单尝试

原创
作者头像
jackieluo
修改2018-09-17 14:38:44
2.5K0
修改2018-09-17 14:38:44
举报

最近用tars框架编写后台服务的时候,逐渐抛弃了之前的异步调用方式,而是使用协程,以同步代码的写法实现并发调用,所以希望可以了解学习一下协程的相关知识。

Python中的yield

Python中有yield的关键词。例如定义一个函数:

def rangeN(a, b):
    i = a
    while(i < b):
        yield i
        i += 1

yeild将函数rangeN(a, b)变成一个generator类,调用它时,执行到yield i时,就返回i,下次迭代时,代码从yield i的下一行,即i += 1开始执行,且函数中的局部变量i保持了上次中断执行前的值。

测试一下它的效果:

for i in rangeN(1, 5):
    print(i)

输出:

1
2
3
4

尝试用C实现协程

难点在于C语言的函数调用是基于栈帧的,每次函数调用,都会初始化一个栈,来存放变量等,函数调用结束时这个栈便会被销毁。

例如下面这个程序:

int read(void) 
{ 
	int i; 
	for (i = 0; i < 10; i++) 
		return i; /* 很明显,根本运行不到10次,在第1次,这个函数就返回了 */
} 

void main(void)
{
    printf("i is %d\n", read());
}

输出:

i is 0

如果要实现协程,那么需要做到两点:

  1. 恢复的时候,能够从函数最后调用的地方继续执行
  2. 数据在一次函数调用结束后不会被销毁

其中第2点,可以使用静态变量保存的方式来实现。但是怎么记住状态,并且回来的时候从最后的状态继续执行?我们可以使用GOTO,但是,搜一下goto,google可以返回你100个不使用它的理由。

所以,尝试使用“Duff's device(达夫设备)”来实现:

#include<stdio.h> 
  
int range(int a, int b) 
{ 
    static long long int i; 
    static int state = 0; 
    printf("Function start,state :%d,i :%d\n", state, i);
    switch (state) 
    { 
    case 0: /* 函数入口 */
        state = 1; 
        for (i = a; i < b; i++) 
        { 
            return i; 
  
        /* 恢复执行 */
        case 1:printf("control at range :%d\n", i); /* 在return后恢复控制 */
        } 
    } 
    state = 0; 
    printf("Function end,state :%d,i :%d\n", state, i);
    return 0; 
} 
  
int main() 
{ 
    int i;
  
    for (; i=range(1, 5);) 
        printf("control at main :%d\n", i); 
  
    return 0; 
}  

输出:

Function start,state :0,i :0
control at main :1
Function start,state :1,i :1
control at range :1
control at main :2
Function start,state :1,i :2
control at range :2
control at main :3
Function start,state :1,i :3
control at range :3
control at main :4
Function start,state :1,i :4
control at range :4
Function end,state :0,i :5

Duff’s Device,达夫设备,是C中switch语句最巧妙的实现。

第二次调用range函数时,由于静态变量state的值已为1,所以程序直接跳过了为i赋值的12行for循环语句,执行17行的case语句。这样就进入了for循环的内部,使得循环结束后,自增值i从上次结束的值开始i++

反复执行上述过程,直到range中的for循环终止,返回0,那么main中的循环也随即终止,执行结束。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Python中的yield
  • 尝试用C实现协程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档