diff options
| author | Tyge Løvset <[email protected]> | 2023-02-24 10:04:29 +0100 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2023-02-24 10:04:29 +0100 |
| commit | 35e872ec6c0c23b0843e81ff886fc7f5742670b1 (patch) | |
| tree | dbfb00f95bde17574b6ec4b98cd3a04bc0dccf40 /include | |
| parent | 95656f384672748dcf02c256e23534728bef80d9 (diff) | |
| download | STC-modified-35e872ec6c0c23b0843e81ff886fc7f5742670b1.tar.gz STC-modified-35e872ec6c0c23b0843e81ff886fc7f5742670b1.zip | |
Replace by ccoro.h
Diffstat (limited to 'include')
| -rw-r--r-- | include/stc/algo/coroutine.h | 134 |
1 files changed, 0 insertions, 134 deletions
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h deleted file mode 100644 index 967928b2..00000000 --- a/include/stc/algo/coroutine.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * coroutine.h is copyright 1995, 2000 Simon Tatham. - * Modernized/improved 2023 Tyge Løvset. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -/* - * Coroutine mechanics, implemented on top of standard ANSI C. See - * https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html for - * a full discussion of the theory behind this. - * - * To use these macros to define a coroutine, you need to write a - * function that looks something like this: - * - * - * int ascending(cco_handle* ctx) { - * cco_context(ctx, - * int idx; - * ); - * - * cco_routine(c, - * for (c->idx = 0; c->idx < 10; c->idx += 1) - * cco_yield(c->idx); - * - * cco_finish:; // add this to support cco_stop! - * ); - * - * return -1; - * } - * - * 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 - * finish. This can make the re-entrant coroutines more useful - * than the static ones, because you can tell when they have - * finished. - * - * This mechanism could have been better implemented using GNU C - * and its ability to store pointers to labels, but sadly this is - * not part of the ANSI C standard and so the mechanism is done by - * case statements instead. That's why you can't put a cco_yield() - * inside a switch-statement. - * - * 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 hnd = 0; - * for (;;) { - * int x = ascending(&hnd); - * if (x == 5) cco_stop(&hnd); - * if (!hnd) break; - * printf("got number %d\n", x); - * - * } - * } - */ -#ifndef STC_COROUTINE_INCLUDED -#define STC_COROUTINE_INCLUDED - -#include <stdlib.h> -#include <assert.h> -/* - * `c_' macros for re-entrant coroutines. - */ -typedef struct ccoHandle { - int cco_line; -} *cco_handle; - -#define cco_context(handle, ...) \ - struct ccoContext { \ - int cco_line; \ - __VA_ARGS__ \ - } **_ccoparam = (struct ccoContext **)handle + 0*sizeof((*(handle))->cco_line) - -#define cco_routine(ctx, ...) \ - if (!*_ccoparam) { \ - *_ccoparam = (struct ccoContext *)malloc(sizeof **_ccoparam); \ - (*_ccoparam)->cco_line = 0; \ - } \ - struct ccoContext *ctx = *_ccoparam; \ - switch (ctx->cco_line) { \ - case 0:; __VA_ARGS__ break; \ - default: assert(!"missing cco_finish:"); \ - } \ - free(ctx), *_ccoparam = NULL - -#define cco_yield(value) \ - do { \ - (*_ccoparam)->cco_line = __LINE__; return value; \ - case __LINE__:; \ - } while (0) - -#define cco_finish case -1 - -static inline cco_handle* cco_stop(cco_handle* handle) - { (*handle)->cco_line = -1; return handle; } - -#endif // STC_COROUTINE_INCLUDED |
