summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-02-23 12:38:38 +0100
committerTyge Løvset <[email protected]>2023-02-23 12:38:38 +0100
commit01f09f3c2f34ae960b091f6d4063750bccd3e777 (patch)
tree4ead1e1a6c89e74997283c5899285929a3c030be
parent4ff4c8d352f76b658214029988eab7ce1d69efe8 (diff)
downloadSTC-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.c24
-rw-r--r--misc/examples/coread.c8
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);
}