setjmp/longjmp其实是C语言标准库中的内容,它被定义在<setjmp.h>头文件中,我认识的相当部分的人包括写过很多年C/C++的都表示没听过,并且他们在了解了一些setjmp的特性和功能之后还不以为然,说我又不会用到它;然而你们想过为什么标准库中会去实现一个相对这么怪异特性的语法支持?原因很简单,就是为了实现协程(cor...
当然 Knuth 的“特例”指的是协程也可以模拟例程那样实现上下级调用关系,这就叫非对称协程(asymmetric coroutines)。 setjmp.h setjmp/longjmp 其实是C语言标准库中的内容,它被定义在<setjmp.h>头文件中,我认识的相当部分的人包括写过很多年C/C++的都表示没听过,并且他们在了解了一些setjmp的特性和功能之后还不以...
setjmp/longjmp 其实是C语言标准库中的内容,它被定义在头文件中,我认识的相当部分的人包括写过很多年C/C++的都表示没听过,并且他们在了解了一些setjmp的特性和功能之后还不以为然,说我又不会用到它;然而你们想过为什么标准库中会去实现一个相对这么怪异特性的语法支持?原因很简单,就是为了实现协程(coroutine),如...
setjmp 也可以用来模拟 coroutine 。但是会遇到一个难以逾越的难点:正确的 coroutine 实现需要为每个 coroutine 配备一个独立的数据栈,这是 setjmp 无法做到的。虽然有一些 C 的 coroutine 库用 setjmp/longjmp 实现。但使用起来都会有一定隐患。多半是在单一栈上预留一块空间,然后给另一个 coroutine 运行时覆盖使用。
要正确的实现 coroutine ,还需要 setcontext 库 ,这已经不是 C 语言的标准库了。 在使用 setjmp 时,最常见的一个错误用法就是对 setjmp 做封装,用一个函数去调用它。比如: int try(breakpoint bp) { return setjmp(bp->jb); } void throw(breakpoint bp) { longjmp(bp->jb,1); } ...
BOOL start_coroutine(pf func, void *arg) { // 保存主程的跳转点 if (0 == setjmp(gCtx.mainBuf)) { func(arg); // 调用函数 return TRUE; } return FALSE; } int main() { // 启动一个协程 start_coroutine(coroutine_function, NULL); ...
这次在实现coroutine的过程中虽然没有使用setjmp来实现, 但是由于setjmp来实现coroutine的所有操作都是可以在用户态进行的, 因此顺便研究了一下setjmp的实现机制. 与我猜测大致一样, 在call stack上来讲setjmp一定先于或等于longjmp处于的位置, 这样其实longjmp所做的不过就是将当前寄存器上下文恢复成setjmp函数保存的值即...
(void *);BOOL start_coroutine(pf func, void *arg){// 保存主程的跳转点if (0 == setjmp(gCtx.mainBuf)){func(arg); // 调用函数returnTRUE;}returnFALSE;}intmain(){// 启动一个协程start_coroutine(coroutine_function,NULL);while (TRUE) // 死循环{printf("\n=== main: working \n");//...
(void*);BOOLstart_coroutine(pf func,void*arg){// 保存主程的跳转点if(0==setjmp(gCtx.mainBuf)){func(arg);// 调用函数returnTRUE;}returnFALSE;}intmain(){// 启动一个协程start_coroutine(coroutine_function,NULL);while(TRUE)// 死循环{printf("\n=== main: working \n");// 模拟耗时操作...
*/\longjmp(coroutine_b->jmp_buf,1)\}\/* setjmp is not 0, so return from longjmp, then coroutine b run continue */\ 示例 #include<setjmp.h>jmp_buf context_main,context_a,context_b;voidpirnt_a();voidprint_b();voidmain(){if(setjmp(context_main)==0){print_a();}else{printf("...