• C/C++中的协程


    传送门 ==>> AutoSAR实战系列300讲「糖果Autosar」总目录
    协程是通用的control structures,其中流控制在两个不同的例程之间协同传递而不会返回。
    如果您使用过 Python 或 C#,您可能知道有一个名为yield的关键字,它允许a loop back and forth between the caller and the called function until the caller is not done with the function or the function terminates because of some logic it is given.

    示例 是使用yield的Python3 代码。

    • Python
    # Python program to generate numbers in a
    # range using yield
    
    def rangeN(a, b):
    	i = a
    	while (i < b):
    		yield i
    		i += 1 # Next execution resumes
    				# from this point
    
    for i in rangeN(1, 5):
    		print(i)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    输出

    1
    2
    3
    4
    
    • 1
    • 2
    • 3
    • 4

    这段代码演示了 yield 的工作原理,并简要介绍了 how the control is changed between the caller and callee。

    1 为什么需要协程?

    要读取文件并在读取一些有意义的数据时对其进行解析, you can either read step by step at each line, which is fine。您也可以将整个内容加载到内存中【对于大型文本案例(例如 Microsoft Word 等文本编辑器)不建议这样做。 】or in modern systems just use Pipes,

    在 The Art of Computer Programming 中,Donald Knuth 提出了解决这类问题的方法。他的回答是完全抛弃堆栈概念。Stop thinking of one process as the caller and the other as the callee,并开始将它们视为合作平等。所以我们现在可以尝试看看如何在 C 中实现同样的效果。

    function read():
       /* reads the content in the desired number 
          of steps and returns back control to parser
          but saves its own state of function. */
    
    function parse():
       a = read()
       while (a)
       {
           // do something
           a = read()
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    实际上,这个结构看起来非常类似于 C 的调用者-被调用者结构。 But what we require here is that the reader must remember its state. It must remember where it was last time when it did the job and should also be re-settable.

    2 如何在 C 中实现协程?

    The challenge is to have coroutines in C language which is itself a stack-based language,即在对 C 语言中的函数调用的每次响应中,都有一个正在初始化的堆栈,该堆栈跟踪其所有变量和常量,并在函数调用时被销毁结束。

    • C
    int read(void)
    {
    	int i;
    	for (i = 0; i < 10; i++)
    		return i; /* Well on the first run itself
    					the function will be destroyed */
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    我们需要做两件事:

    1. 将控制恢复到上一个状态
    2. Make data persist through calls

    上述这两个问题都应该通过使用静态变量来解决。但是如何记住状态并返回到与之前相同的执行状态,即返回或循环之后的代码行。我们可以使用 GOTO 语句,一般不推荐。关于在c语言实现协程,请看如下代码的实现,

    • C++
    • C
    // C++ program to demonstrate how coroutines
    // can be implemented in C++.
    #include 
    using namespace std;
    
    int range(int a, int b)
    {
    	static long long int i;
    	static int state = 0;
    	switch (state) 
    	{
    		case 0: /* start of function */
    			state = 1;
    			for (i = a; i < b; i++) 
    			{
    				return i;
    
    				/* Returns control */
    				case 1:
    					cout << "control at range"
    					<< endl; /* resume control straight
    						after the return */
    			}
    	}
    	state = 0;
    	return 0;
    }
    
    // Driver code
    int main()
    {
    	int i; // For really large numbers
    
    	for (; i = range(1, 5);)
    		cout << "control at main :" << i << endl;
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    输出

    control at main :1
    control at range
    control at main :2
    control at range
    control at main :3
    control at range
    control at main :4
    control at range
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    We can now essentially have multiple return statements inside the for loop and each time we return to a different state of execution if it’s programmed to do so。这个实现只模仿了Python 的 range 函数,它也是基于协程的。

  • 相关阅读:
    Python 中的 Urljoin 简介
    1384. 按年度列出销售总额
    .Net Core 实现WebSocket Server 的另外三种方式
    HaaS学习笔记 | 终端设备接入和断开阿里云IoT物联网平台的明细教程
    js---async和awit的一些理解
    SDS-redis动态字符串
    刷刷shell提总结下— 不用总忘还是常总结啊
    python自动化测试selenium核心技术3种等待方式详解
    【分享课】11月16日晚19:30PostgreSQL分享课:PG缓存管理器主题
    机器学习中的基础问题总结
  • 原文地址:https://blog.csdn.net/huihuige092/article/details/126029645