如何在c中的for循环中实现协程

How to implement coroutine within for loop in c

这是部分代码:

void a()
{
    printf("entering a\n");
    int i;
    for(i = 0; i < 3; i++){
        if(setjmp(a_buf) == 0) {
            printf("A step %d\n", i);
            b();
        } else {
            longjmp(b_buf, 1);
        }
    }
    printf("returning from a\n");
}

void b()
{
    printf("entering b\n");
    int i;
    for(i = 0; i < 5; i++){
        if(setjmp(b_buf) == 0) {
            printf("B step %d\n", i);
            a();
        } else {
            longjmp(a_buf, 1);
        }
    }
    printf("returning from b\n");
}

我有两个进程 ab。如何使它们作为协程工作。 希望他们做 A Step 0 然后 B Step 0 然后回到 A Step 1... 直到都完成。但看起来计数器 i 从未改变。

setjmp()longjmp() 函数只能用于退出嵌套子程序,作为一种 "throw/catch"。它们不能用于重新进入已经退出的子程序,无论是通过 return 还是通过 longjmp()。总之,不能这样用。

在 C 中实现协程的唯一定义明确的方法是 as a state machine。无法将协程实现为普通子例程,因为这与 C 堆栈不兼容。

您在此处使用代码尝试实现的目标未定义。

引用 C11,章节 §7.13.2.1p2

The longjmp function restores the environment saved by the most recent invocation of the setjmp macro in the same invocation of the program with the corresponding jmp_buf argument. If there has been no such invocation, or if the invocation was from another thread of execution, or if the function containing the invocation of the setjmp macro has terminated execution in the interim, or if the invocation of the setjmp macro was within the scope of an identifier with variably modified type and execution has left that scope in the interim, the behavior is undefined.

Emphasis mine

关于什么算作终止执行:

引用 C11,章节 §note248

For example, by executing a return statement or because another longjmp call has caused a transfer to a setjmp invocation in a function earlier in the set of nested calls.

因此,假设您先调用 a(),它在设置 a_buf 后调用 b()。现在 b() 设置 b_buf 并跳回 a。此时 b 的执行已终止,如果您跳回到 b_buf,则行为未定义。

您的问题的一个可能解决方案是定义函数 a_step()b_step(),它们分别只执行 a()b() 的一个步骤。然后在循环中交替调用它们。

请看"s_task"协程,或许就是你的答案--

https://github.com/xhawk18/s_task

特征--

  1. 用纯 c 和 asm 编写,不需要 c++
  2. 来自 boost context 的 asm 代码,健壮且有效
  3. 添加关键字 awaitasync
  4. 支持各种平台,如windows、linux(arm,x8​​6,mips)、stm32、stm8
  5. 已集成 libuv 进行网络编程
  6. "event" 和 "mutex" 协程之间通信的对象