diff options
Diffstat (limited to 'misc/examples/algo/coroutines.c')
| -rw-r--r-- | misc/examples/algo/coroutines.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/misc/examples/algo/coroutines.c b/misc/examples/algo/coroutines.c new file mode 100644 index 00000000..2c9e6d5c --- /dev/null +++ b/misc/examples/algo/coroutines.c @@ -0,0 +1,105 @@ +#include <stc/algo/coroutine.h> +#include <stdio.h> +#include <stdint.h> + +// Demonstrate to call another coroutine from a coroutine: +// First create prime generator, then call fibonacci sequence: + +bool is_prime(int64_t i) { + for (int64_t j=2; j*j <= i; ++j) + if (i % j == 0) return false; + return true; +} + +struct prime { + int count, idx; + int64_t result, pos; + int cco_state; +}; + +bool prime(struct prime* U) { + cco_begin(U); + if (U->result < 2) U->result = 2; + if (U->result == 2) { + if (U->count-- == 0) cco_return; + ++U->idx; + cco_yield(true); + } + U->result += !(U->result & 1); + for (U->pos = U->result; U->count > 0; U->pos += 2) { + if (is_prime(U->pos)) { + --U->count; + ++U->idx; + U->result = U->pos; + cco_yield(true); + } + } + cco_final: + printf("final prm\n"); + cco_end(false); +} + + +// Use coroutine to create a fibonacci sequence generator: + +struct fibonacci { + int count, idx; + int64_t result, b; + int cco_state; +}; + +bool fibonacci(struct fibonacci* F) { + assert(F->count < 94); + + cco_begin(F); + F->idx = 0; + F->result = 0; + F->b = 1; + for (;;) { + if (F->count-- == 0) + cco_return; + if (++F->idx > 1) { + int64_t sum = F->result + F->b; // NB! locals only lasts until next cco_yield! + F->result = F->b; + F->b = sum; + } + cco_yield(true); + } + cco_final: + printf("final fib\n"); + cco_end(false); +} + +// Combine + +struct combined { + struct prime prm; + struct fibonacci fib; + int cco_state; +}; + +bool combined(struct combined* C) { + cco_begin(C); + cco_yield(prime(&C->prm), &C->prm, true); + cco_yield(fibonacci(&C->fib), &C->fib, true); + + // Reuse the C->prm context and extend the count: + C->prm.count = 8; C->prm.result += 2; + cco_yield(prime(&C->prm), &C->prm, true); + + cco_final: puts("final comb"); + cco_end(false); +} + +int main(void) { + struct combined comb = {.prm={.count=8}, .fib={14}}; + if (true) + while (combined(&comb)) + printf("Prime(%d)=%lld, Fib(%d)=%lld\n", + comb.prm.idx, (long long)comb.prm.result, + comb.fib.idx, (long long)comb.fib.result); + else + while (prime(&comb.prm)) + printf("Prime(%d)=%lld\n", + comb.prm.idx, (long long)comb.prm.result); +} |
