协程的用处
同步的编程方式,异步I/O性能
协程代码分析
setjmp/longjmp
ucontext
setjmp
#include<stdio.h>
#include<setjmp.h>
jmp_buf env;
void func(int arg){
printf("func:%d\n",arg);
longjmp(env,++arg);
}
int main()
{
int ret=setjmp(env);
if(ret==0){
func(ret);}
else if(ret==1){
func(ret);}
else if(ret==2){
func(ret);}
else if(ret==3){
func(ret);}
return 0;
}
逻辑还是比较清晰明了,可以自己体会。
context
#include<stdio.h>
#include<ucontext.h>
ucontext_t ctx[2];
ucontext_t main_ctx;
int count=0;
void func1(void){
while(count++<20){
printf("1\n");
swapcontext(&ctx[0],&ctx[1]);
printf("3\n");}}
void func2(void){
while(count++<20){
printf("2\n");
swapcontext(&ctx[1],&ctx[0]);
printf("4\n");}}
int main(){
char stack1[2048]={0};
char stack2[2048]={0};
getcontext(&ctx[0]);
ctx[0].uc_stack.ss_sp=stack1;
ctx[0].uc_stack.ss_size=sizeof(stack1);
ctx[0].uc_link=&main_ctx;
makecontext(&ctx[0],func1,0);
getcontext(&ctx[1]);
ctx[1].uc_stack.ss_sp=stack2;
ctx[1].uc_stack.ss_size=sizeof(stack2);
ctx[1].uc_link=&main_ctx;
makecontext(&ctx[1],func2,0);
printf("swapcontext\n");
swapcontext(&main_ctx,&ctx[0]);
printf("\n");
}
在主函数中分别设置两个上下文指针,用指针指向函数的上下文并初始化,从swapcontext开始循环。
协程调度器实现
ucontext_t ctx[2];
ucontext_t main_ctx;
int count=0;
void func1(void){
while(count++<20){
printf("1\n");
//swapcontext(&ctx[0],&ctx[1]);
swapcontext(&ctx[0],&main_ctx);
printf("3\n");}}
void func2(void){
while(count++<20){
printf("2\n");
//swapcontext(&ctx[1],&ctx[0]);
swapcontext(&ctx[1],&main_ctx);
printf("4\n");}}
//schedule
int main(){
char stack1[2048]={0};
char stack2[2048]={0};
getcontext(&ctx[0]);
ctx[0].uc_stack.ss_sp=stack1;
ctx[0].uc_stack.ss_size=sizeof(stack1);
ctx[0].uc_link=&main_ctx;
makecontext(&ctx[0],func1,0);
getcontext(&ctx[1]);
ctx[1].uc_stack.ss_sp=stack2;
ctx[1].uc_stack.ss_size=sizeof(stack2);
ctx[1].uc_link=&main_ctx;
makecontext(&ctx[1],func2,0);
printf("swapcontext\n");
while(count<30){
swapcontext(&main_ctx,&ctx[count%2]);}
printf("\n");
}
将主函数设置为一个调度器,实现协程func1和func2的调度和切换,效果和上面是一样的