本篇使用上一篇提供的接口,实现一个简单的协程调度框架.
基本思想是,创建一个调度器,用于将处于活动状态的协程调度运行,调度器维护着一个actived列表,
调用spawn创建协程时,将新建立的协程添加到活动列表中。
调用schedule将启动调度器主循环.
coro.h
#ifndef _CORO_H#define _CORO_H#include#include "uthread.h"struct coro{ struct coro *next; uthread_t ut; uint32_t id; start_fun st_fun; uint32_t is_end;};struct testarg{ struct coro *sche; struct coro *co;};void* yield(struct coro*,struct coro*,void *);void* resume(struct coro*,struct coro*,void *);struct scheduler{ struct coro *active; //处于激活态的coro struct coro *self;};struct scheduler *scheduler_create();//生成一个coro运行start_runvoid spawn(struct scheduler*,void *stack,uint32_t stack_size,start_fun);//调度coro运行void schedule(struct scheduler*);#endif coro.c
#include "coro.h"#include#include void* yield(struct coro *from,struct coro *to,void *arg){ return uthread_swtch(from->ut,to->ut,arg);}void* resume(struct coro *from,struct coro *to,void *arg){ return uthread_swtch(from->ut,to->ut,arg);}static uint32_t g_index = 0;static void* coro_start_fun(void *arg){ struct testarg *_arg = (struct testarg *)arg; void *ret = _arg->co->st_fun(_arg); _arg->co->is_end = 1; return ret;}void spawn(struct scheduler *sche,void *stack,uint32_t stack_size,start_fun st_fun){ uthread_t ut = uthread_create(stack,stack_size); struct coro *co = (struct coro*)malloc(sizeof(*co)); co->ut = ut; co->st_fun = st_fun; co->id = ++g_index; //添加到激活队列中 co->next = sche->active; co->is_end = 0; sche->active = co; uthread_make(co->ut,sche->self->ut,coro_start_fun);}struct scheduler *scheduler_create(){ struct scheduler *sche = (struct scheduler *)malloc(sizeof(*sche)); sche->active = 0; sche->self = (struct coro*)malloc(sizeof(*sche->self)); sche->self->ut = uthread_create(0,0); return sche;}void schedule(struct scheduler *sche){ while(1) { if(sche->active) { struct coro *cur = sche->active; sche->active = 0; while(cur) { struct testarg arg = {sche->self,cur}; resume(sche->self,cur,&arg); struct coro *tmp = cur->next; if(!cur->is_end) { cur->next = sche->active; sche->active = cur; cur = tmp; } else { uthread_destroy(&(cur->ut)); free(cur); } cur = tmp; } } else break; }} test.c
#include#include #include #include "uthread.h"#include "coro.h"void* fun(void *arg){ struct testarg *_arg = (struct testarg *)arg; int i = 0; while(i<10) { printf("%d\n",_arg->co->id); yield(_arg->co,_arg->sche,0); ++i; } return 0;}int main(){ struct scheduler *sche = scheduler_create(); spawn(sche,malloc(4096),4096,fun); spawn(sche,malloc(4096),4096,fun); spawn(sche,malloc(4096),4096,fun); spawn(sche,malloc(4096),4096,fun); schedule(sche); return 0;}