windows 纤程(fiber) 实现的协程
2017-01-14 15:05
169 查看
参考云风的协程库实现:https://github.com/cloudwu/coroutine
云风的协程为 非对称的共享栈协程
以下为fiber实现的非对称协程:
环境:win7、VS2013
头文件: (coroutine.h)
源文件:(coroutine.c)
测试程序:(main.c)
云风的协程为 非对称的共享栈协程
以下为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 3 typedef 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; // 当前协程ID LPVOID 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; }
相关文章推荐
- 《Windows via C/C++》学习笔记 —— 纤程(Fiber)
- 基于纤程(Fiber)实现C++异步编程库(一):原理及示例
- 《Windows via C/C++》学习笔记 —— 纤程(Fiber)
- Windows下实现协程-Coroutine
- Windows的纤程(Fiber)
- windows下利用协程实现gevent版服务器
- Windows Via C/C++ 读书笔记 8 Fiber(纤程)
- Thread(线程)、Fiber(纤程)、coroutine(协程) 之间的区别以及...
- [导入]如何实现立体的DataGrid和具有Windows效果的图片按钮
- 用API实现WINDOWS下的通用对话框!
- WINDOWS (服务器) 和 DOS(客户端) 网络互连 基于TCP/IP的编程实现
- 在ASP.Net 中使用实现windows登陆的方法. (轉自tainkai的專欄.http://blog.csdn.net/tainkai)
- 基于多线程技术和自定义消息编程实现Windows 9x异步串行通信
- 如何实现立体的DataGrid和具有Windows效果的图片按钮
- 实现仿Windows程序无刷新的Web应用
- Windows 2003下实现无盘工作站
- 在ASP.Net 中使用实现windows登陆的方法.
- WINDOWS (服务器) 和 DOS(客户端) 网络互连 基于TCP/IP的编程实现
- Windows 2000/XP 下实现休眠