summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-02-28 08:40:40 +0100
committerTyge Løvset <[email protected]>2023-02-28 08:40:40 +0100
commit0fb86f00db4f1d3600ec1b91d0a4e2ef8f778164 (patch)
treeb2b65809bda272f73fa06147df549e6f889886b5
parentd2228c3dc993e47c8d2df951230cf43a93299f5f (diff)
downloadSTC-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.h20
-rw-r--r--misc/examples/coroutines.c43
-rw-r--r--misc/examples/triples.c13
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