如何在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");
}
我有两个进程 a
和 b
。如何使它们作为协程工作。
希望他们做 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
特征--
- 用纯 c 和 asm 编写,不需要 c++
- 来自 boost context 的 asm 代码,健壮且有效
- 添加关键字 await 和 async
- 支持各种平台,如windows、linux(arm,x86,mips)、stm32、stm8
- 已集成 libuv 进行网络编程
- "event" 和 "mutex" 协程之间通信的对象
这是部分代码:
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");
}
我有两个进程 a
和 b
。如何使它们作为协程工作。
希望他们做 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 thesetjmp
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 thesetjmp
macro has terminated execution in the interim, or if the invocation of thesetjmp
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 asetjmp
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
特征--
- 用纯 c 和 asm 编写,不需要 c++
- 来自 boost context 的 asm 代码,健壮且有效
- 添加关键字 await 和 async
- 支持各种平台,如windows、linux(arm,x86,mips)、stm32、stm8
- 已集成 libuv 进行网络编程
- "event" 和 "mutex" 协程之间通信的对象