From 6434174c7ef5a614bcb9cdf79fb0d8668af032c7 Mon Sep 17 00:00:00 2001 From: ssrlive <30760636+ssrlive@users.noreply.github.com> Date: Fri, 25 Mar 2022 16:38:54 +0800 Subject: [PATCH 1/7] Update coroutine.c --- coroutine.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/coroutine.c b/coroutine.c index 58a90e0..7a4e5b7 100644 --- a/coroutine.c +++ b/coroutine.c @@ -6,11 +6,12 @@ #include #include +#if defined(__unix__) || defined(__APPLE__) + #if __APPLE__ && __MACH__ - #include -#else - #include -#endif +#define _XOPEN_SOURCE 600 +#endif +#include #define STACK_SIZE (1024*1024) #define DEFAULT_COROUTINE 16 @@ -190,3 +191,4 @@ coroutine_running(struct schedule * S) { return S->running; } +#endif /* defined(__unix__) || defined(__APPLE__) */ From c542b268eda3779022bc99c132878b7b307c008e Mon Sep 17 00:00:00 2001 From: ssrlive <30760636+ssrlive@users.noreply.github.com> Date: Fri, 25 Mar 2022 16:40:33 +0800 Subject: [PATCH 2/7] Add files via upload --- coroutine-win.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 coroutine-win.c diff --git a/coroutine-win.c b/coroutine-win.c new file mode 100644 index 0000000..ccc000e --- /dev/null +++ b/coroutine-win.c @@ -0,0 +1,137 @@ +#include +#include +#include + +#ifdef WIN32 +#include "coroutine.h" +#include + +#define DEFAULT_COROUTINE 16 + +struct coroutine; + +struct schedule { + void *fiber_ctx; + int cap; + int running; + struct coroutine **co; +}; + +struct coroutine { + coroutine_func func; + void *ud; + void *fiber_ctx; + struct schedule * sch; + size_t sch_index; + int status; +}; + +struct schedule * coroutine_open(void) { + struct schedule *sch = (struct schedule *) calloc(1, sizeof(*sch)); + sch->cap = DEFAULT_COROUTINE; + sch->running = -1; + sch->co = (struct coroutine**) calloc(sch->cap, sizeof(struct coroutine *)); + sch->fiber_ctx = ConvertThreadToFiber(NULL); + return sch; +} + +void _co_delete(struct coroutine *co) { + DeleteFiber(co->fiber_ctx); + free(co); +} + +void __stdcall fiber_func(void *p) { + struct coroutine * co = (struct coroutine *) p; + struct schedule *sch = (struct schedule *)co->sch; + size_t id = co->sch_index; + assert( (0 <= id) && (id < sch->cap) ); + co->func(sch, co->ud); + co->status = COROUTINE_DEAD; // Just mark it dead, can't delete it. + sch->running = -1; + SwitchToFiber(sch->fiber_ctx); +} + +struct coroutine * _co_new(struct schedule *sch, size_t index, coroutine_func func, void *ud) { + struct coroutine * co = (struct coroutine *) calloc(1, sizeof(*co)); + co->func = func; + co->ud = ud; + co->sch = sch; + co->sch_index = index; + co->status = COROUTINE_READY; + co->fiber_ctx = CreateFiber(0, fiber_func, co); + return co; +} + +void coroutine_close(struct schedule *sch) { + int i; + for (i=0; i < sch->cap; i++) { + struct coroutine * co = sch->co[i]; + if (co) { + _co_delete(co); + } + } + free(sch->co); + sch->co = NULL; + free(sch); +} + +int coroutine_new(struct schedule *sch, coroutine_func func, void *ud) { + int id; + for (id = 0; id < sch->cap; ++id) { + struct coroutine *co = sch->co[id]; + if (co == NULL || co->status == COROUTINE_DEAD) { + if (co && co->status == COROUTINE_DEAD) { + _co_delete(co); + } + sch->co[id] = _co_new(sch, id, func, ud); + return id; + } + } + sch->co = (struct coroutine **) realloc(sch->co, sch->cap * 2 * sizeof(struct coroutine *)); + assert(sch->co); + memset(sch->co + sch->cap , 0, sizeof(struct coroutine *) * sch->cap); + sch->co[id] = _co_new(sch, id, func, ud); + sch->cap *= 2; + return id; +} + +void coroutine_resume(struct schedule *sch, int id) { + struct coroutine *co; + assert(sch->running == -1); + assert(id >=0 && id < sch->cap); + if ((co = sch->co[id]) == NULL) { + return; + } + switch(co->status) { + case COROUTINE_READY: + case COROUTINE_SUSPEND: + sch->running = id; + co->status = COROUTINE_RUNNING; + SwitchToFiber(co->fiber_ctx); + break; + default: + assert(0); + } +} + +int coroutine_status(struct schedule *sch, int id) { + assert((id >= 0) && (id < sch->cap)); + if (sch->co[id] == NULL) { + return COROUTINE_DEAD; + } + return sch->co[id]->status; +} + +int coroutine_running(struct schedule *sch) { + return sch->running; +} + +void coroutine_yield(struct schedule *sch) { + int id = sch->running; + assert(id >= 0); + sch->co[id]->status = COROUTINE_SUSPEND; + sch->running = -1; + SwitchToFiber(sch->fiber_ctx); +} + +#endif /* WIN32 */ From b8e8ca03d67684390aadd133b19536ff179ca8df Mon Sep 17 00:00:00 2001 From: ssrlive <30760636+ssrlive@users.noreply.github.com> Date: Fri, 25 Mar 2022 16:45:08 +0800 Subject: [PATCH 3/7] Add files via upload --- CMakeLists.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c838f08 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.0) + +project(coroutine) + +set(LIBCOROUTINEDIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "coroutine library" FORCE) + +include(CMakeDependentOption) +cmake_dependent_option(LIBCOROUTINE_IS_ROOT_PROJECT + "coroutine is root project" + ON "CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF) + +add_library(coroutine coroutine.c coroutine-win.c) + +if (LIBCOROUTINE_IS_ROOT_PROJECT) +add_executable(demo main.c) +target_link_libraries(demo coroutine) +endif() From f7cd4c3cb628c24fd1b878d53d95aa1bba13d513 Mon Sep 17 00:00:00 2001 From: ssrlive <30760636+ssrlive@users.noreply.github.com> Date: Sat, 26 Mar 2022 07:26:51 +0800 Subject: [PATCH 4/7] index issues. --- coroutine-win.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/coroutine-win.c b/coroutine-win.c index ccc000e..d6b38a4 100644 --- a/coroutine-win.c +++ b/coroutine-win.c @@ -22,7 +22,7 @@ struct coroutine { void *ud; void *fiber_ctx; struct schedule * sch; - size_t sch_index; + int index; int status; }; @@ -43,20 +43,20 @@ void _co_delete(struct coroutine *co) { void __stdcall fiber_func(void *p) { struct coroutine * co = (struct coroutine *) p; struct schedule *sch = (struct schedule *)co->sch; - size_t id = co->sch_index; - assert( (0 <= id) && (id < sch->cap) ); + int index = co->index; + assert( (0 <= index) && (index < sch->cap) ); co->func(sch, co->ud); co->status = COROUTINE_DEAD; // Just mark it dead, can't delete it. sch->running = -1; SwitchToFiber(sch->fiber_ctx); } -struct coroutine * _co_new(struct schedule *sch, size_t index, coroutine_func func, void *ud) { +struct coroutine * _co_new(struct schedule *sch, int index, coroutine_func func, void *ud) { struct coroutine * co = (struct coroutine *) calloc(1, sizeof(*co)); co->func = func; co->ud = ud; co->sch = sch; - co->sch_index = index; + co->index = index; co->status = COROUTINE_READY; co->fiber_ctx = CreateFiber(0, fiber_func, co); return co; From 5bed758a25bd2c7fb2639226210f0eb1f4d6dfcc Mon Sep 17 00:00:00 2001 From: ssrlive <30760636+ssrlive@users.noreply.github.com> Date: Sat, 26 Mar 2022 12:02:36 +0800 Subject: [PATCH 5/7] unique_id logic. --- coroutine-win.c | 93 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 31 deletions(-) diff --git a/coroutine-win.c b/coroutine-win.c index d6b38a4..ca29dbe 100644 --- a/coroutine-win.c +++ b/coroutine-win.c @@ -11,32 +11,50 @@ struct coroutine; struct schedule { - void *fiber_ctx; + void *fiber; int cap; - int running; + int running_index; struct coroutine **co; + int unique_id; }; struct coroutine { coroutine_func func; void *ud; - void *fiber_ctx; + void *fiber; struct schedule * sch; int index; + int unique_id; int status; }; +int generate_id(struct schedule *sch) { + return ++sch->unique_id; +} + +struct coroutine * get_coroutine_from_id(struct schedule *sch, int id) { + int index; + struct coroutine *co; + for (index = 0; index < sch->cap; ++index) { + struct coroutine *co = sch->co[index]; + if (co && co->unique_id == id) { + return co; + } + } + return NULL; +} + struct schedule * coroutine_open(void) { struct schedule *sch = (struct schedule *) calloc(1, sizeof(*sch)); sch->cap = DEFAULT_COROUTINE; - sch->running = -1; + sch->running_index = -1; sch->co = (struct coroutine**) calloc(sch->cap, sizeof(struct coroutine *)); - sch->fiber_ctx = ConvertThreadToFiber(NULL); + sch->fiber = ConvertThreadToFiber(NULL); return sch; } void _co_delete(struct coroutine *co) { - DeleteFiber(co->fiber_ctx); + DeleteFiber(co->fiber); free(co); } @@ -47,8 +65,8 @@ void __stdcall fiber_func(void *p) { assert( (0 <= index) && (index < sch->cap) ); co->func(sch, co->ud); co->status = COROUTINE_DEAD; // Just mark it dead, can't delete it. - sch->running = -1; - SwitchToFiber(sch->fiber_ctx); + sch->running_index = -1; + SwitchToFiber(sch->fiber); } struct coroutine * _co_new(struct schedule *sch, int index, coroutine_func func, void *ud) { @@ -57,8 +75,9 @@ struct coroutine * _co_new(struct schedule *sch, int index, coroutine_func func, co->ud = ud; co->sch = sch; co->index = index; + co->unique_id = generate_id(sch); co->status = COROUTINE_READY; - co->fiber_ctx = CreateFiber(0, fiber_func, co); + co->fiber = CreateFiber(0, fiber_func, co); return co; } @@ -76,38 +95,45 @@ void coroutine_close(struct schedule *sch) { } int coroutine_new(struct schedule *sch, coroutine_func func, void *ud) { - int id; - for (id = 0; id < sch->cap; ++id) { - struct coroutine *co = sch->co[id]; + int index; + struct coroutine *co; + for (index = 0; index < sch->cap; ++index) { + struct coroutine *co = sch->co[index]; if (co == NULL || co->status == COROUTINE_DEAD) { if (co && co->status == COROUTINE_DEAD) { _co_delete(co); } - sch->co[id] = _co_new(sch, id, func, ud); - return id; + co = _co_new(sch, index, func, ud); + sch->co[index] = co; + return co->unique_id; } } sch->co = (struct coroutine **) realloc(sch->co, sch->cap * 2 * sizeof(struct coroutine *)); assert(sch->co); memset(sch->co + sch->cap , 0, sizeof(struct coroutine *) * sch->cap); - sch->co[id] = _co_new(sch, id, func, ud); + co = _co_new(sch, index, func, ud); + sch->co[index] = co; sch->cap *= 2; - return id; + return co->unique_id; } void coroutine_resume(struct schedule *sch, int id) { - struct coroutine *co; - assert(sch->running == -1); - assert(id >=0 && id < sch->cap); - if ((co = sch->co[id]) == NULL) { + struct coroutine *co = get_coroutine_from_id(sch, id); + int index; + if (co == NULL) { + assert(!"something went wrong!"); return; } + index = co->index; + assert(sch->running_index == -1); + assert(0 <= index && index < sch->cap); + assert(co == sch->co[index]); switch(co->status) { case COROUTINE_READY: case COROUTINE_SUSPEND: - sch->running = id; + sch->running_index = index; co->status = COROUTINE_RUNNING; - SwitchToFiber(co->fiber_ctx); + SwitchToFiber(co->fiber); break; default: assert(0); @@ -115,23 +141,28 @@ void coroutine_resume(struct schedule *sch, int id) { } int coroutine_status(struct schedule *sch, int id) { - assert((id >= 0) && (id < sch->cap)); - if (sch->co[id] == NULL) { + struct coroutine *co = get_coroutine_from_id(sch, id); + int index; + if (co == NULL) { + assert(!"something went wrong!"); return COROUTINE_DEAD; } - return sch->co[id]->status; + index = co->index; + assert((0 <= index) && (index < sch->cap)); + return co->status; } int coroutine_running(struct schedule *sch) { - return sch->running; + int index = sch->running_index; + return index >= 0 ? sch->co[index]->unique_id : -1; } void coroutine_yield(struct schedule *sch) { - int id = sch->running; - assert(id >= 0); - sch->co[id]->status = COROUTINE_SUSPEND; - sch->running = -1; - SwitchToFiber(sch->fiber_ctx); + int index = sch->running_index; + assert(index >= 0); + sch->co[index]->status = COROUTINE_SUSPEND; + sch->running_index = -1; + SwitchToFiber(sch->fiber); } #endif /* WIN32 */ From 04733ceeb19c565e98992dbe877e1958485e8a86 Mon Sep 17 00:00:00 2001 From: ssrlive <30760636+ssrlive@users.noreply.github.com> Date: Sat, 26 Mar 2022 19:18:41 +0800 Subject: [PATCH 6/7] Update coroutine-win.c --- coroutine-win.c | 1 - 1 file changed, 1 deletion(-) diff --git a/coroutine-win.c b/coroutine-win.c index ca29dbe..2a8e45e 100644 --- a/coroutine-win.c +++ b/coroutine-win.c @@ -34,7 +34,6 @@ int generate_id(struct schedule *sch) { struct coroutine * get_coroutine_from_id(struct schedule *sch, int id) { int index; - struct coroutine *co; for (index = 0; index < sch->cap; ++index) { struct coroutine *co = sch->co[index]; if (co && co->unique_id == id) { From 7524fb094d75da54d63c630c31ab0067e7e854c1 Mon Sep 17 00:00:00 2001 From: ssrlive <30760636+ssrlive@users.noreply.github.com> Date: Sun, 27 Mar 2022 12:19:53 +0800 Subject: [PATCH 7/7] Update coroutine.c --- coroutine.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/coroutine.c b/coroutine.c index 7a4e5b7..847c55c 100644 --- a/coroutine.c +++ b/coroutine.c @@ -6,9 +6,9 @@ #include #include -#if defined(__unix__) || defined(__APPLE__) +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -#if __APPLE__ && __MACH__ +#if defined(__APPLE__) && defined(__MACH__) #define _XOPEN_SOURCE 600 #endif #include @@ -191,4 +191,4 @@ coroutine_running(struct schedule * S) { return S->running; } -#endif /* defined(__unix__) || defined(__APPLE__) */ +#endif /* defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) */