还好云风实现过一个coroutine库,用的context系列函数,很精巧的封装,代码量很小, 也没附加啥其它特性。用来加深理解再好不过。
在 http://blog.codingnow.com/2012/07/c_coroutine.html 上有其相关说明。
不过代码没注释啥的,为了怕忘记一些体会,我按个人理解加了代码注释, 在上Github上保存了一份.
https://github.com/xcltapestry/coroutine (理解不深,如有错误欢迎指正).1. 结构体schedule与coroutine的参数意义
struct schedule { char stack[STACK_SIZE]; //运行时,co上下文用的就是这块内存. 厉害 ucontext_t main; //上下文信息 int nco; //实际的co指针个数 int cap; //co指针数组大小 int running; // 当前处理的co数组id 或 -1 struct coroutine **co; //co指针数组 }; // ptrdiff_t 用于表示指针间的"距离",对于指针加减的结果可用这个类型来表示. struct coroutine { coroutine_func func; //用户自定义的函数 void *ud; //用户自定义的函数,所传进来的参数,在此为main中的statuc arg ucontext_t ctx; //上下文信息就不用多说了 struct schedule * sch; //指向co所归属的Sch. ptrdiff_t cap; //容量 ptrdiff_t size; //占用的栈大小 int status; // COROUTINE_SUSPEND/COROUTINE_READY char *stack; //在yield/resume时发挥保存和恢复作用 };
//注意这里从兼容性角度把S这个指针拆了下,原因是大部份编译器在32/64位下, //sizeof(指针)返回的长度是不一样的, 32位下是4个字节,64位下是8个字节 //所以在makecontext()的这个可变参数中,将其拆分成了两个32位的指针来传. //附:在执行地址运算时,多用 uintptr_t 和 uint32_t,更清晰,安全性与兼容性更好 uintptr_t ptr = (uintptr_t)S; makecontext(&C->ctx, (void (*)(void)) mainfunc, 2, (uint32_t)ptr, (uint32_t)(ptr>>32));