最近用tars框架编写后台服务的时候,逐渐抛弃了之前的异步调用方式,而是使用协程,以同步代码的写法实现并发调用,所以希望可以了解学习一下协程的相关知识。
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语言的函数调用是基于栈帧的,每次函数调用,都会初始化一个栈,来存放变量等,函数调用结束时这个栈便会被销毁。
例如下面这个程序:
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
如果要实现协程,那么需要做到两点:
其中第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 删除。