summaryrefslogtreecommitdiffhomepage
path: root/misc/examples/algo/coroutines.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc/examples/algo/coroutines.c')
-rw-r--r--misc/examples/algo/coroutines.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/misc/examples/algo/coroutines.c b/misc/examples/algo/coroutines.c
new file mode 100644
index 00000000..2c9e6d5c
--- /dev/null
+++ b/misc/examples/algo/coroutines.c
@@ -0,0 +1,105 @@
+#include <stc/algo/coroutine.h>
+#include <stdio.h>
+#include <stdint.h>
+
+// Demonstrate to call another coroutine from a coroutine:
+// First create prime generator, then call fibonacci sequence:
+
+bool is_prime(int64_t i) {
+ for (int64_t j=2; j*j <= i; ++j)
+ if (i % j == 0) return false;
+ return true;
+}
+
+struct prime {
+ int count, idx;
+ int64_t result, pos;
+ int cco_state;
+};
+
+bool prime(struct prime* U) {
+ cco_begin(U);
+ if (U->result < 2) U->result = 2;
+ if (U->result == 2) {
+ if (U->count-- == 0) cco_return;
+ ++U->idx;
+ cco_yield(true);
+ }
+ 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->pos;
+ cco_yield(true);
+ }
+ }
+ cco_final:
+ printf("final prm\n");
+ cco_end(false);
+}
+
+
+// Use coroutine to create a fibonacci sequence generator:
+
+struct fibonacci {
+ int count, idx;
+ int64_t result, b;
+ int cco_state;
+};
+
+bool fibonacci(struct fibonacci* F) {
+ assert(F->count < 94);
+
+ cco_begin(F);
+ F->idx = 0;
+ F->result = 0;
+ F->b = 1;
+ for (;;) {
+ if (F->count-- == 0)
+ cco_return;
+ if (++F->idx > 1) {
+ int64_t sum = F->result + F->b; // NB! locals only lasts until next cco_yield!
+ F->result = F->b;
+ F->b = sum;
+ }
+ cco_yield(true);
+ }
+ cco_final:
+ printf("final fib\n");
+ cco_end(false);
+}
+
+// Combine
+
+struct combined {
+ struct prime prm;
+ struct fibonacci fib;
+ int cco_state;
+};
+
+bool combined(struct combined* C) {
+ cco_begin(C);
+ cco_yield(prime(&C->prm), &C->prm, true);
+ cco_yield(fibonacci(&C->fib), &C->fib, true);
+
+ // Reuse the C->prm context and extend the count:
+ C->prm.count = 8; C->prm.result += 2;
+ cco_yield(prime(&C->prm), &C->prm, true);
+
+ cco_final: puts("final comb");
+ cco_end(false);
+}
+
+int main(void) {
+ struct combined comb = {.prm={.count=8}, .fib={14}};
+ if (true)
+ while (combined(&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);
+}