diff options
| author | Tyge Løvset <[email protected]> | 2023-02-28 08:40:40 +0100 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2023-02-28 08:40:40 +0100 |
| commit | 0fb86f00db4f1d3600ec1b91d0a4e2ef8f778164 (patch) | |
| tree | b2b65809bda272f73fa06147df549e6f889886b5 | |
| parent | d2228c3dc993e47c8d2df951230cf43a93299f5f (diff) | |
| download | STC-modified-0fb86f00db4f1d3600ec1b91d0a4e2ef8f778164.tar.gz STC-modified-0fb86f00db4f1d3600ec1b91d0a4e2ef8f778164.zip | |
Fixed coroutine.h and examples. cco_return; has no arguments.
| -rw-r--r-- | include/stc/algo/coroutine.h | 20 | ||||
| -rw-r--r-- | misc/examples/coroutines.c | 43 | ||||
| -rw-r--r-- | misc/examples/triples.c | 13 |
3 files changed, 45 insertions, 31 deletions
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h index 150fa9ec..395a19cb 100644 --- a/include/stc/algo/coroutine.h +++ b/include/stc/algo/coroutine.h @@ -62,19 +62,20 @@ int main(void) { enum { cco_state_final = -1, - cco_state_done = -2, + cco_state_expired = -2, cco_state_illegal = -3, }; #define cco_begin(ctx) \ int *_state = &(ctx)->cco_state; \ switch (*_state) { \ - case 0: \ - case cco_state_done:; + case cco_state_expired: \ + case 0:; \ #define cco_end(retval) \ - *_state = cco_state_done; break; \ + *_state = cco_state_expired; break; \ default: assert(!"missing cco_final: or illegal state"); \ + goto cco_finish; /* avoid unused warning */ \ } \ return retval @@ -84,18 +85,21 @@ enum { case __LINE__:; \ } while (0) +#define cco_return \ + do { \ + *_state = cco_state_final; goto cco_finish; \ + } while (0) + #define cco_coroutine(corocall, ctx, retval) \ do { \ *_state = __LINE__; \ - c_PASTE(cco, __LINE__): corocall; return retval; \ + c_PASTE(cco, __LINE__): corocall; if (cco_alive(ctx)) return retval; \ case __LINE__: if (cco_alive(ctx)) goto c_PASTE(cco, __LINE__); \ } while (0) -#define cco_final case cco_state_final +#define cco_final case cco_state_final: cco_finish #define cco_stop(ctx) (((ctx)->cco_state = cco_alive(ctx) ? \ cco_state_final : cco_state_illegal), ctx) -#define cco_reset(ctx) ((ctx)->cco_state = 0) -#define cco_done(ctx) ((ctx)->cco_state == cco_state_done) #define cco_alive(ctx) ((ctx)->cco_state > 0) #endif diff --git a/misc/examples/coroutines.c b/misc/examples/coroutines.c index 0588c2ea..867d02a8 100644 --- a/misc/examples/coroutines.c +++ b/misc/examples/coroutines.c @@ -13,26 +13,29 @@ bool is_prime(int64_t i) { struct prime { int count, idx; - int64_t num, result; + int64_t result, pos; int cco_state; }; bool prime(struct prime* U) { cco_begin(U); - if (U->num < 2) U->num = 2; - if (U->num == 2) { + if (U->result < 2) U->result = 2; + if (U->result == 2) { + if (U->count-- == 0) cco_return; ++U->idx; - U->result = U->num; cco_yield(true); } - U->num += !(U->num & 1); - for (; U->idx < U->count; U->num += 2) - if (is_prime(U->num)) { + 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->num; + U->result = U->pos; cco_yield(true); } + } cco_final: + printf("final prm\n"); cco_end(false); } @@ -45,21 +48,23 @@ struct fibonacci { int cco_state; }; -int64_t fibonacci(struct fibonacci* F) { - assert (F->count < 94); +bool fibonacci(struct fibonacci* F) { + assert(F->count < 94); cco_begin(F); - F->idx = 0; + F->idx = 1; F->result = 0; F->b = 1; - for (F->idx = 1; F->idx < F->count; F->idx++) { - cco_yield(F->result); + for (;; F->idx++) { + if (F->count-- == 0) cco_return; + cco_yield(true); int64_t sum = F->result + F->b; // NB! locals only lasts until next cco_yield! F->result = F->b; F->b = sum; } cco_final: - cco_end(-1); + printf("final fib\n"); + cco_end(false); } // Combine @@ -85,11 +90,13 @@ bool combine(struct combine* C) { int main(void) { struct combine comb = {.prm={.count=10}, .fib={14}}; - while (combine(&comb)) - if (cco_done(&comb.prm)) - cco_reset(&comb.prm); - else + if (true) + while (combine(&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); } diff --git a/misc/examples/triples.c b/misc/examples/triples.c index e85558a3..05e6fca2 100644 --- a/misc/examples/triples.c +++ b/misc/examples/triples.c @@ -18,22 +18,27 @@ void triples_vanilla(int n) { } struct tricoro { + int n; int cco_state; int x, y, z; }; +#include <stdlib.h> + bool triples_coro(struct tricoro* t) { cco_begin(t); for (t->z = 1;; ++t->z) { for (t->x = 1; t->x < t->z; ++t->x) { for (t->y = t->x; t->y < t->z; ++t->y) { if (t->x*t->x + t->y*t->y == t->z*t->z) { + if (t->n-- == 0) cco_return; cco_yield(true); } } } } cco_final: + puts("final"); cco_end(false); } @@ -41,12 +46,10 @@ bool triples_coro(struct tricoro* t) { int main() { puts("Vanilla triples:"); - triples_vanilla(20); + triples_vanilla(6); puts("\nCoroutine triples:"); - struct tricoro t = {0}; - int i = 0; - while (i++ < 20 && triples_coro(&t)) + struct tricoro t = {6}; + while (triples_coro(&t)) printf("{%d, %d, %d},\n", t.x, t.y, t.z); - triples_coro(cco_stop(&t)); }
\ No newline at end of file |
