diff options
| author | Tyge Løvset <[email protected]> | 2023-05-02 07:20:29 +0200 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2023-05-02 07:20:29 +0200 |
| commit | 2adea8b3b06ebe1b2152870862100f7e7985cfdf (patch) | |
| tree | 7d37dc14784f33e9b40888253aa5c7183d81c6b0 /misc/examples | |
| parent | 399eb8d0e1de2839d826a9e0cf123d90d00b0018 (diff) | |
| download | STC-modified-2adea8b3b06ebe1b2152870862100f7e7985cfdf.tar.gz STC-modified-2adea8b3b06ebe1b2152870862100f7e7985cfdf.zip | |
Improved coroutine.h, added new coro examples.
Diffstat (limited to 'misc/examples')
| -rw-r--r-- | misc/examples/cointerleave.c | 60 | ||||
| -rw-r--r-- | misc/examples/coread.c | 14 | ||||
| -rw-r--r-- | misc/examples/coroutines.c | 20 | ||||
| -rw-r--r-- | misc/examples/scheduler.c | 76 | ||||
| -rw-r--r-- | misc/examples/triples.c | 8 |
5 files changed, 157 insertions, 21 deletions
diff --git a/misc/examples/cointerleave.c b/misc/examples/cointerleave.c new file mode 100644 index 00000000..64473d96 --- /dev/null +++ b/misc/examples/cointerleave.c @@ -0,0 +1,60 @@ +// https://www.youtube.com/watch?v=8sEe-4tig_A +#include <stc/calgo.h> +#include <stdio.h> +#define i_type IVec +#define i_val int +#include <stc/cvec.h> + +struct GenValue { + IVec *v; + IVec_iter it; + int cco_state; +}; + +static int next_value(struct GenValue* g) +{ + cco_begin(g); + for (g->it = IVec_begin(g->v); g->it.ref; IVec_next(&g->it)) + cco_yield(*g->it.ref); + cco_final: + cco_end(0); +} + +struct Generator { + struct GenValue x, y; + int cco_state; + int value; +}; + +bool interleaved(struct Generator* g) +{ + cco_begin(g); + while (cco_alive(&g->x) || cco_alive(&g->y)) + { + g->value = next_value(&g->x); + if (cco_alive(&g->x)) cco_yield(false); + + g->value = next_value(&g->y); + if (cco_alive(&g->y)) cco_yield(false); + } + cco_final: + cco_end(true); +} + +void Use(void) +{ + IVec a = c_make(IVec, {2, 4, 6, 8, 10, 11}); + IVec b = c_make(IVec, {3, 5, 7, 9}); + + struct Generator g = {{&a}, {&b}}; + + while (!interleaved(&g)) + printf("%d\n", g.value); + + c_drop(IVec, &a, &b); +} + +int main() +{ + Use(); +} diff --git a/misc/examples/coread.c b/misc/examples/coread.c index 0a7f4816..d5385a87 100644 --- a/misc/examples/coread.c +++ b/misc/examples/coread.c @@ -4,36 +4,36 @@ // Read file line by line using coroutines: -struct file_nextline { +struct file_read { const char* filename; int cco_state; FILE* fp; cstr line; }; -bool file_nextline(struct file_nextline* U) +bool file_read(struct file_read* U) { cco_begin(U) U->fp = fopen(U->filename, "r"); U->line = cstr_init(); while (cstr_getline(&U->line, U->fp)) - cco_yield(true); + cco_yield(false); cco_final: // this label is required. printf("finish\n"); cstr_drop(&U->line); fclose(U->fp); - cco_end(false); + cco_end(true); } int main(void) { - struct file_nextline it = {__FILE__}; + struct file_read g = {__FILE__}; int n = 0; - while (file_nextline(&it)) + while (!file_read(&g)) { - printf("%3d %s\n", ++n, cstr_str(&it.line)); + printf("%3d %s\n", ++n, cstr_str(&g.line)); //if (n == 10) cco_stop(&it); } } diff --git a/misc/examples/coroutines.c b/misc/examples/coroutines.c index af9fef81..3fddf913 100644 --- a/misc/examples/coroutines.c +++ b/misc/examples/coroutines.c @@ -23,7 +23,7 @@ bool prime(struct prime* U) { if (U->result == 2) { if (U->count-- == 0) cco_return; ++U->idx; - cco_yield(true); + cco_yield(false); } U->result += !(U->result & 1); for (U->pos = U->result; U->count > 0; U->pos += 2) { @@ -31,12 +31,12 @@ bool prime(struct prime* U) { --U->count; ++U->idx; U->result = U->pos; - cco_yield(true); + cco_yield(false); } } cco_final: printf("final prm\n"); - cco_end(false); + cco_end(true); } @@ -63,11 +63,11 @@ bool fibonacci(struct fibonacci* F) { F->result = F->b; F->b = sum; } - cco_yield(true); + cco_yield(false); } cco_final: printf("final fib\n"); - cco_end(false); + cco_end(true); } // Combine @@ -81,23 +81,23 @@ struct combined { bool combined(struct combined* C) { cco_begin(C); - cco_await(prime(&C->prm) == false); - cco_await(fibonacci(&C->fib) == false); + cco_await(prime(&C->prm)); + cco_await(fibonacci(&C->fib)); // Reuse the C->prm context and extend the count: C->prm.count = 8; C->prm.result += 2; cco_reset(&C->prm); - cco_await(prime(&C->prm) == false); + cco_await(prime(&C->prm)); cco_final: puts("final comb"); - cco_end(false); + cco_end(true); } int main(void) { struct combined comb = {.prm={.count=8}, .fib={14}}; - while (combined(&comb)) + 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); diff --git a/misc/examples/scheduler.c b/misc/examples/scheduler.c new file mode 100644 index 00000000..1809f2ec --- /dev/null +++ b/misc/examples/scheduler.c @@ -0,0 +1,76 @@ +// https://www.youtube.com/watch?v=8sEe-4tig_A +#include <stdio.h> +#include <stc/calgo.h> + +struct Scheduler; +struct Task { + bool (*resume)(struct Task*); + struct Scheduler* sched; + int cco_state; +}; + +#define i_type Scheduler +#define i_val struct Task +#define i_no_cmp +#include <stc/clist.h> + +static bool schedule(Scheduler* sched) +{ + struct Task task = *Scheduler_front(sched); + Scheduler_pop_front(sched); + + if (cco_alive(&task)) + task.resume(&task); + + return !Scheduler_empty(sched); +} + +static bool resume_task(const struct Task* task) +{ + Scheduler_push_back(task->sched, *task); + return false; +} + + +static bool taskA(struct Task* task) +{ + cco_begin(task); + puts("Hello, from task A"); + cco_yield(resume_task(task)); + puts("A is back doing work"); + cco_yield(resume_task(task)); + puts("A is back doing more work"); + cco_yield(resume_task(task)); + puts("A is back doing even more work"); + cco_final: + cco_end(true); +} + +static bool taskB(struct Task* task) +{ + cco_begin(task); + puts("Hello, from task B"); + cco_yield(resume_task(task)); + puts("B is back doing work"); + cco_yield(resume_task(task)); + puts("B is back doing more work"); + cco_final: + cco_end(true); +} + +void Use(void) +{ + Scheduler scheduler = c_make(Scheduler, { + {taskA, &scheduler}, + {taskB, &scheduler}, + }); + + while (schedule(&scheduler)) {} + + Scheduler_drop(&scheduler); +} + +int main() +{ + Use(); +} diff --git a/misc/examples/triples.c b/misc/examples/triples.c index 520bf012..2e0211c3 100644 --- a/misc/examples/triples.c +++ b/misc/examples/triples.c @@ -23,13 +23,13 @@ struct triples { int cco_state; }; -bool triples_next(struct triples* I) { +bool triples_coro(struct triples* I) { cco_begin(I); for (I->c = 5; I->n; ++I->c) { for (I->a = 1; I->a < I->c; ++I->a) { for (I->b = I->a + 1; I->b < I->c; ++I->b) { if ((int64_t)I->a*I->a + (int64_t)I->b*I->b == (int64_t)I->c*I->c) { - cco_yield(true); + cco_yield(false); if (--I->n == 0) cco_return; } } @@ -37,7 +37,7 @@ bool triples_next(struct triples* I) { } cco_final: puts("done"); - cco_end(false); + cco_end(true); } int gcd(int a, int b) { @@ -58,7 +58,7 @@ int main() struct triples t = {INT32_MAX}; int n = 0; - while (triples_next(&t)) { + while (!triples_coro(&t)) { if (gcd(t.a, t.b) > 1) continue; if (t.c < 100) |
