diff options
| -rw-r--r-- | include/stc/algo/ccoro.h | 15 | ||||
| -rw-r--r-- | misc/examples/cofib.c | 43 | ||||
| -rw-r--r-- | misc/examples/cosub.c | 65 |
3 files changed, 73 insertions, 50 deletions
diff --git a/include/stc/algo/ccoro.h b/include/stc/algo/ccoro.h index f5c682e8..07f98bf4 100644 --- a/include/stc/algo/ccoro.h +++ b/include/stc/algo/ccoro.h @@ -67,20 +67,21 @@ int main(void) { } \ *_state = -2 -#define ccoro_yield(...) c_MACRO_OVERLOAD(ccoro_yield, __VA_ARGS__) -#define ccoro_yield_1(value) \ +#define ccoro_yield(ret) \ do { \ - *_state = __LINE__; return value; \ + *_state = __LINE__; return ret; \ case __LINE__:; \ } while (0) -#define ccoro_yield_2(subcoro, c) \ +#define ccoro_yield_call(...) c_MACRO_OVERLOAD(ccoro_yield_call, __VA_ARGS__) +#define ccoro_yield_call_2(c, subcoro) ccoro_yield_call_3(c, subcoro, ) +#define ccoro_yield_call_3(c, subcoro, ret) \ do { \ *_state = __LINE__; \ - c_PASTE(coro, __LINE__): \ - return subcoro; \ + c_PASTE(co, __LINE__): \ + subcoro; return ret; \ case __LINE__:; \ - if (ccoro_alive(c)) goto c_PASTE(coro, __LINE__); \ + if (ccoro_alive(c)) goto c_PASTE(co, __LINE__); \ } while (0) #define ccoro_final case -1 diff --git a/misc/examples/cofib.c b/misc/examples/cofib.c deleted file mode 100644 index b58775ae..00000000 --- a/misc/examples/cofib.c +++ /dev/null @@ -1,43 +0,0 @@ -#include <stc/algo/ccoro.h> -#include <stdio.h> -#include <stdint.h> - -// Use coroutine to create a fibonacci sequence generator: - -typedef long long llong; -struct fibonacci { - int n; - int ccoro_state; - llong a, b, idx; -}; - -llong fibonacci(struct fibonacci* U) { - assert (U->n < 95); - - ccoro_execute(U, - U->a = 0; - U->b = 1; - for (U->idx = 0; U->idx < U->n; U->idx++) { - ccoro_yield (U->a); - llong sum = U->a + U->b; // NB! locals only lasts until next ccoro_yield! - U->a = U->b; - U->b = sum; - } - ccoro_final: - ); - - return -1; -} - - -int main(void) { - printf("Fibonacci numbers:\n"); - struct fibonacci fib = {.n = 14}; - - for (;;) { - llong x = fibonacci(&fib); - if (!ccoro_alive(&fib)) break; - printf(" %lld", x); - } - puts(""); -} diff --git a/misc/examples/cosub.c b/misc/examples/cosub.c new file mode 100644 index 00000000..0aee7aee --- /dev/null +++ b/misc/examples/cosub.c @@ -0,0 +1,65 @@ +#include <stc/algo/ccoro.h> +#include <stdio.h> +#include <stdint.h> + +// Use coroutine to create a fibonacci sequence generator: + +typedef long long intll_t; + +struct fibonacci { + int n; + int ccoro_state; + intll_t a, b, idx; +}; + +intll_t fibonacci(struct fibonacci* F) { + assert (F->n < 95); + + ccoro_execute(F, + F->a = 0; + F->b = 1; + for (F->idx = 0; F->idx < F->n; F->idx++) { + ccoro_yield (F->a); + intll_t sum = F->a + F->b; // NB! locals only lasts until next ccoro_yield! + F->a = F->b; + F->b = sum; + } + ccoro_final: + ); + + return -1; +} + +// Demonstrate to call another coroutine from a coroutine: +// Create a 2D iterator, and call fibonacci sequence when x,y = 1,1: + +struct iterate { + int max_x, max_y; + int ccoro_state; + int x, y; +}; + +bool iterate(struct iterate* I, struct fibonacci* F) { + ccoro_execute(I, + for (I->x = 0; I->x < I->max_x; I->x++) + for (I->y = 0; I->y < I->max_y; I->y++) + if (I->x == 1 && I->y == 1) + ccoro_yield_call (F, fibonacci(F), true); + else + ccoro_yield (true); + ccoro_finish: + ); + return false; +} + + +int main(void) { + printf("Fibonacci numbers:\n"); + struct fibonacci fib = {.n = 14}; + struct iterate iter = {3, 3}; + + while (iterate(&iter, &fib)) + printf("%d %d. Fib: %lld\n", iter.x, iter.y, fib.a); + + puts(""); +} |
