C协程使用举例
本篇使用上一篇提供的接口,实现一个简单的协程调度框架.
基本思想是,创建一个调度器,用于将处于活动状态的协程调度运行,调度器维护着一个actived列表,
调用spawn创建协程时,将新建立的协程添加到活动列表中。
调用schedule将启动调度器主循环.
coro.h
#ifndef _CORO_H #define _CORO_H #include <stdint.h> #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_run void spawn( struct scheduler*, void * stack,uint32_t stack_size,start_fun); // 调度coro运行 void schedule( struct scheduler* ); #endifcoro.c
#include " coro.h " #include <stdlib.h> #include <time.h> 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 <stdio.h> #include <stdlib.h> #include <stdint.h> #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 ; }