windows 纤程(fiber) 实现的协程

来源:互联网 发布:单片机 usb 虚拟串口 编辑:程序博客网 时间:2024/06/04 23:27

参考云风的协程库实现:https://github.com/cloudwu/coroutine

云风的协程为 非对称的共享栈协程

以下为fiber实现的非对称协程:


环境:win7、VS2013


头文件: (coroutine.h)

#ifndef __COROUTINE__H__#define __COROUTINE__H__#define COROUTINE_DEAD     0#define COROUTINE_READY    1#define COROUTINE_RUNNING  2#define COROUTINE_SUSPEND  3typedef struct schedule schedule;typedef void(*coroutine_func)(schedule *s, void *ud);schedule *coroutine_open();void coroutine_close(schedule *s);int coroutine_new(schedule *s, coroutine_func *, void *ud);void coroutine_resume(schedule *s, int id);void coroutine_yield(schedule *s);int coroutine_status(schedule *s, int id);int coroutine_running(schedule *s);#endif

源文件:(coroutine.c)

#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <assert.h>#include "coroutine.h"/* windows fiber版本的协程yield的时候直接切换到主协程(main),而不是swapcontext的切换到上次运行协程,但最后达到的结果却一样*/// 默认容量#define DEFAULT_CAP   8// 堆栈大小#define INIT_STACK    1048576 //(1024*1024)typedef struct schedule schedule;typedef struct coroutine coroutine;typedef struct coroutine_para coroutine_para;struct schedule{int  cap;     // 容量int  conums;int  curID;   // 当前协程IDLPVOID    main;coroutine **co;};struct coroutine{schedule  *s;void      *ud;int       status;LPVOID    ctx;coroutine_func func;};static int co_putin(schedule *s, coroutine *co){if (s->conums >= s->cap){int id = s->cap;s->co = realloc(s->co, sizeof(coroutine *) * s->cap * 2);memset(&s->co[s->cap], 0, sizeof(coroutine *) * s->cap);s->co[s->cap] = co;s->cap *= 2;++s->conums;return id;}else{for (int i = 0; i < s->cap; i++){int id = (i + s->conums) % s->cap;if (s->co[id] == NULL){s->co[id] = co;++s->conums;return id;}}}assert(0);return -1;}static void co_delete(coroutine *co){//If the currently running fiber calls DeleteFiber, its thread calls ExitThread and terminates.    //However, if a currently running fiber is deleted by another fiber, the thread running the //deleted fiber is likely to terminate abnormally because the fiber stack has been freed.DeleteFiber(co->ctx);free(co);}schedule *coroutine_open(){schedule *s = malloc(sizeof(schedule));s->cap = DEFAULT_CAP;s->conums = 0;s->curID = -1;s->co = malloc(sizeof(coroutine *) * s->cap);memset(s->co, 0, sizeof(coroutine *) * s->cap);s->main = ConvertThreadToFiberEx(NULL, FIBER_FLAG_FLOAT_SWITCH);return s;}void coroutine_close(schedule *s){for (int i = 0; i < s->cap; i++){coroutine *co = s->co[i];if (co) co_delete(co);}free(s->co);s->co = NULL;free(s);}void __stdcall coroutine_main(LPVOID lpParameter){schedule* s = (schedule*)lpParameter;int id = s->curID;coroutine *co = s->co[id];(co->func)(s, co->ud);s->curID = -1;--s->conums;s->co[id] = NULL;//co_delete(co);SwitchToFiber(s->main);}int coroutine_new(schedule *s, coroutine_func *func, void *ud){coroutine *co = malloc(sizeof(coroutine));co->s = s;co->status = COROUTINE_READY;co->func = func;co->ud = ud;int id = co_putin(s, co);co->ctx = CreateFiberEx(INIT_STACK, 0, FIBER_FLAG_FLOAT_SWITCH, coroutine_main, s);co->status = COROUTINE_READY;return id;}void coroutine_resume(schedule *s, int id){assert(id >= 0 && id < s->cap);if (id < 0 || id >= s->cap) return;coroutine *co = s->co[id];if (co == NULL) return;switch (co->status){case COROUTINE_READY:case COROUTINE_SUSPEND:co->status = COROUTINE_RUNNING;s->curID = id;SwitchToFiber(co->ctx);if (!s->co[id]) co_delete(co);break;default:assert(0);break;}}void coroutine_yield(schedule *s){int id = s->curID;assert(id >= 0 && id < s->cap);if (id < 0) return;coroutine *co = s->co[id];co->status = COROUTINE_SUSPEND;s->curID = -1;SwitchToFiber(s->main);}int coroutine_status(schedule *s, int id){assert(id >= 0 && id < s->cap);if (id < 0) return;if (s->co[id] == NULL) {return COROUTINE_DEAD;}return s->co[id]->status;}int coroutine_running(schedule *s){return s->curID;}


测试程序:(main.c)

#include "coroutine.h"void test3(schedule *s, void *ud){int *data = (int*)ud;for (int i = 0; i < 3; i++){printf("test3 i=%d\n",i);coroutine_yield(s);printf("yield co id = %d.\n", *data);}}void coroutine_test(){printf("coroutine_test3 begin\n");schedule *s = coroutine_open();int a = 11;int id1 = coroutine_new(s, test3, &a);int id2 = coroutine_new(s, test3, &a);while (coroutine_status(s, id1) && coroutine_status(s, id2)){printf("\nresume co id = %d.\n",id1);coroutine_resume(s, id1);//printf("resume co id = %d.\n", id2);//coroutine_resume(s, id2);}int id3 = coroutine_new(s, test3, &a);while (coroutine_status(s, id3)){printf("\nresume co id = %d.\n", id3);coroutine_resume(s, id3);}printf("coroutine_test3 end\n");coroutine_close(s);}int main(){coroutine_test();return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 多囊卵泡不排卵怎么办 卵泡两天长2mm怎么办 子宫小43*38*26怎么办 优势卵泡打破卵针后并不破怎么办 ktv禁止自带酒水怎么办 记名西瓜卡丢了怎么办 日本电车卡丢了怎么办 网贷暂时没钱还怎么办 华泰倒闭了汽车怎么办 猫躲起来找不到了怎么办 狗生病了不吃饭怎么办 猫猫托运后害怕怎么办 新来的猫害怕怎么办 升工资老板不公平对待怎么办 自酿啤酒苦味重怎么办 自酿啤酒酸味重怎么办 微信电话费充错了怎么办 支付宝电话费充错了怎么办 在淘宝上充错电话费了怎么办 话费1000充错了怎么办 东西掉在地铁上怎么办 高铁安检丢东西怎么办 东西掉成都地铁上怎么办 东西掉在成都地铁上怎么办 成都地铁上掉东西了怎么办 地铁站丢了东西怎么办 在地铁站丢了东西怎么办 没有签劳动合同不发工资怎么办 没有劳动合同辞职不给工资怎么办 地铁安检要交押金怎么办 在广州地铁上人走丢了怎么办 海尔全自动洗衣机程系乱了怎么办 河南危险化学品经营许可证怎么办 甲方不给付监理费怎么办 甲方不按合同付工程款怎么办 撞车对方全责不赔钱怎么办 电梯坏了没人修怎么办 电工超作证丢了怎么办 设计师直接找电梯厂家怎么办 研究生补助申请期限过了怎么办 我的电脑图标没了怎么办