欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

理解无栈协程

时间:2023-04-28

c++20加入了协程,为了性能实现的是无栈协程。有栈协程与无栈协程和有栈协程与无栈协程对协程的两种实现做了介绍,简单来说有栈协程是可以中断并恢复执行的subroutine,无栈协程是状态机。
使用 C 语言实现协程中介绍的这个无栈协程实现可以帮助更好的理解为什么说无栈协程是状态机。

coroutine.h只用三个宏(这里有简化)就实现了一个不可重入的无栈协程:

#define scrBegin static int scrLine=0; switch(scrLine) { case 0:#define scrReturn(z) { scrLine=__LINE__; return (z); case __LINE__:; }#define scrFinish(z) } return (z)

用一个例子来了解它的实现:

int fibonacci(){ static int a=1, b=1; scrBegin; scrReturn(1); scrReturn(1); for(;;) { b += a; a = b - a; scrReturn(b); } scrFinish(0);}

这个函数用来计算斐波那契数列,把宏展开等价于:

int fibonacci(){ static int a=1, b=1; static int state=0; switch(state) { case 0: {state=1; return 1; case 1:;} {state=2; return 1; case 2:;} for(;;) { b += a; a = b - a; {state=3; return b; case 3:;} } } return 0;}

这里需要说明下switch case语句,case语句属于Labeled statements,就是goto后边的那个标签,任何一条语句都能在自己前面声明一个标识符作为标签名称,标签本身并不会改变控制流。所以case放在{}中或for循环中是没问题的。case 3后面跟了一条空语句是因为标签后面得有一条语句。
scrReturn带有{}是为了支持跟在if语句后且没被{}包裹的情况。
c语言里的循环,可以认为是goto语句的语法糖,例如:

int test(){ int sum = 0; for(int i=0; i<10; ++i) sum += i; return sum;}

int test(){ int sum = 0; { int i=0;loop: if(i<10) { sum += i; ++i; goto loop; } } return sum;}

是完全等价的。所以fibonacci就可以改写为:

int fibonacci(){ static int a=1, b=1; static int state=0; switch(state) { case 0: state=1; return 1; case 1: state=2; return 1; case 2: loop: b += a; a = b - a; state=3; return b; case 3: goto loop; } return 0;}

这个状态机就很明显了。

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。