diff options
| author | Tyge Løvset <[email protected]> | 2023-02-23 12:38:38 +0100 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2023-02-23 12:38:38 +0100 |
| commit | 01f09f3c2f34ae960b091f6d4063750bccd3e777 (patch) | |
| tree | 4ead1e1a6c89e74997283c5899285929a3c030be | |
| parent | 4ff4c8d352f76b658214029988eab7ce1d69efe8 (diff) | |
| download | STC-modified-01f09f3c2f34ae960b091f6d4063750bccd3e777.tar.gz STC-modified-01f09f3c2f34ae960b091f6d4063750bccd3e777.zip | |
Renamed cco.h to coroutine.h
| -rw-r--r-- | include/stc/algo/coroutine.h (renamed from include/stc/algo/cco.h) | 46 | ||||
| -rw-r--r-- | misc/examples/cofib.c | 24 | ||||
| -rw-r--r-- | misc/examples/coread.c | 8 |
3 files changed, 39 insertions, 39 deletions
diff --git a/include/stc/algo/cco.h b/include/stc/algo/coroutine.h index c94382b1..cf7acc16 100644 --- a/include/stc/algo/cco.h +++ b/include/stc/algo/coroutine.h @@ -31,7 +31,6 @@ * To use these macros to define a coroutine, you need to write a * function that looks something like this: * - * [Re-entrant version using an explicit context structure] * * int ascending(cco_handle* ctx) { * cco_context(ctx, @@ -44,12 +43,12 @@ * * cco_finish:; // add this to support cco_stop! * ); + * * return -1; * } * - * In the re-entrant version, you need to declare your persistent - * variables by the `cco_context' macro. This macro takes the - * cco_handle as first parameter. + * You declare your persistent variables with the `cco_context' + * macro. This macro takes the cco_handle as first parameter. * * Note that the context variable is set back to zero when the * coroutine terminates (by cco_stop, or by control reaching @@ -63,42 +62,43 @@ * case statements instead. That's why you can't put a cco_yield() * inside a switch-statement. * - * The re-entrant macros will malloc() the state structure on first - * call, and free() it when end is reached. If you want to - * abort in the middle, you can use, the caller should call the - * coroutine with `cco_stop(&ctx)' as parameter instead of &ctx alone. + * The macros will malloc() the state structure on first call, and + * free() it when end is reached. If you want to abort in the middle, + * the caller must call the coroutine with `cco_stop(&ctx)' as + * parameter instead of &ctx. + * * * Ground rules: * - never put `cco_yield' within an explicit `switch'. * - never put two `cco_yield' statements on the same source line. * - add `cco_finish:' label at the end of the coroutine, before * any cleanup code. Required to support cco_stop(ctx) argument. + * - in order to stop before all items are consumed, call the + * coroutine with `cco_stop(&handle)' as argument at the end. * * The caller of a re-entrant coroutine must provide a context * variable: * * void main(void) { - * cco_handle z = 0; + * cco_handle hnd = 0; * for (;;) { - * int x = ascending(&z); - * if (!z) break; + * int x = ascending(&hnd); + * if (x == 5) cco_stop(&hnd); + * if (!hnd) break; * printf("got number %d\n", x); * - * // stop if x == 5: - * if (x == 5) ascending(cco_stop(&z)); * } * } */ - -#ifndef COROUTINE_H -#define COROUTINE_H +#ifndef STC_COROUTINE_INCLUDED +#define STC_COROUTINE_INCLUDED #include <stdlib.h> #include <assert.h> /* * `c_' macros for re-entrant coroutines. */ -typedef struct { +typedef struct ccoHandle { int cco_line; } *cco_handle; @@ -116,19 +116,19 @@ typedef struct { struct ccoContext *ctx = *_ccoparam; \ switch (ctx->cco_line) { \ case 0: __VA_ARGS__ break; \ - default: assert(!"cco_finish: missing"); \ + default: assert(!"missing cco_finish:"); \ } \ free(ctx), *_ccoparam = NULL -#define cco_yield(ret) \ +#define cco_yield(value) \ do { \ - (*_ccoparam)->cco_line = __LINE__; return ret; \ + (*_ccoparam)->cco_line = __LINE__; return value; \ case __LINE__:; \ } while (0) #define cco_finish case -1 -#define cco_stop(ctx) \ - ((*(ctx))->cco_line = -1, (ctx)) +static inline cco_handle* cco_stop(cco_handle* handle) + { (*handle)->cco_line = -1; return handle; } -#endif /* COROUTINE_H */ +#endif // STC_COROUTINE_INCLUDED diff --git a/misc/examples/cofib.c b/misc/examples/cofib.c index 2363989a..ea37669a 100644 --- a/misc/examples/cofib.c +++ b/misc/examples/cofib.c @@ -1,4 +1,4 @@ -#include <stc/algo/cco.h> +#include <stc/algo/coroutine.h> #include <stdio.h> #include <stdint.h> @@ -12,19 +12,19 @@ llong fibonacci_sequence(cco_handle* z, unsigned n) { cco_context(z, llong a, b, idx; ); - - cco_routine(u, - u->a = 0; - u->b = 1; - for (u->idx = 2; u->idx < n; u->idx++) { - llong sum = u->a + u->b; // NB! locals only lasts until a cco_yield! - u->a = u->b; - u->b = sum; - cco_yield (sum); + cco_routine(U, + U->a = 0; + U->b = 1; + for (U->idx = 0; U->idx < n; U->idx++) { + cco_yield (U->a); + llong sum = U->a + U->b; // NB! locals only lasts until next cco_yield! + U->a = U->b; + U->b = sum; } cco_finish: ); - return 0; + + return -1; } @@ -32,7 +32,7 @@ int main(void) { cco_handle z = 0; printf("Fibonacci numbers:\n"); for (;;) { - llong x = fibonacci_sequence(&z, 30); + llong x = fibonacci_sequence(&z, 14); if (!z) break; printf(" %lld", x); } diff --git a/misc/examples/coread.c b/misc/examples/coread.c index 55e4bf21..e65ab533 100644 --- a/misc/examples/coread.c +++ b/misc/examples/coread.c @@ -1,5 +1,5 @@ #include <stc/cstr.h> -#include <stc/algo/cco.h> +#include <stc/algo/coroutine.h> #include <errno.h> // Read file line by line using coroutines: @@ -10,7 +10,6 @@ cstr file_nextline(cco_handle* z, const char* name) FILE* fp; cstr line; ); - cco_routine(U, U->fp = fopen(name, "r"); U->line = cstr_NULL; @@ -23,6 +22,7 @@ cstr file_nextline(cco_handle* z, const char* name) cstr_drop(&U->line); fclose(U->fp); ); + return cstr_NULL; } @@ -34,8 +34,8 @@ int main(void) { c_with (cstr line = file_nextline(&z, __FILE__), z, cstr_drop(&line)) { printf("%3d %s\n", ++n, cstr_str(&line)); - // stop after 10 lines: - if (n == 10) file_nextline(cco_stop(&z), __FILE__); + // stop after 15 lines: + if (n == 15) file_nextline(cco_stop(&z), __FILE__); } } while (z); } |
