summaryrefslogtreecommitdiffhomepage
path: root/misc/examples/coroutines/coroutines.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc/examples/coroutines/coroutines.c')
-rw-r--r--misc/examples/coroutines/coroutines.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/misc/examples/coroutines/coroutines.c b/misc/examples/coroutines/coroutines.c
new file mode 100644
index 00000000..802a976a
--- /dev/null
+++ b/misc/examples/coroutines/coroutines.c
@@ -0,0 +1,112 @@
+#include <stc/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(long long i) {
+ for (long long j=2; j*j <= i; ++j)
+ if (i % j == 0) return false;
+ return true;
+}
+
+struct prime {
+ int count, idx;
+ long long result, pos;
+ int cco_state;
+};
+
+int prime(struct prime* g) {
+ cco_routine(g) {
+ if (g->result < 2) g->result = 2;
+ if (g->result == 2) {
+ if (g->count-- == 0) cco_return;
+ ++g->idx;
+ cco_yield();
+ }
+ g->result += !(g->result & 1);
+ for (g->pos = g->result; g->count > 0; g->pos += 2) {
+ if (is_prime(g->pos)) {
+ --g->count;
+ ++g->idx;
+ g->result = g->pos;
+ cco_yield();
+ }
+ }
+ cco_final:
+ printf("final prm\n");
+ }
+ return 0;
+}
+
+
+// Use coroutine to create a fibonacci sequence generator:
+
+struct fibonacci {
+ int count, idx;
+ long long result, b;
+ int cco_state;
+};
+
+int fibonacci(struct fibonacci* g) {
+ assert(g->count < 94);
+
+ long long sum;
+ cco_routine(g) {
+ g->idx = 0;
+ g->result = 0;
+ g->b = 1;
+ for (;;) {
+ if (g->count-- == 0)
+ cco_return;
+ if (++g->idx > 1) {
+ // NB! locals lasts only until next yield/await!
+ sum = g->result + g->b;
+ g->result = g->b;
+ g->b = sum;
+ }
+ cco_yield();
+ }
+ cco_final:
+ printf("final fib\n");
+ }
+ return 0;
+}
+
+// Combine
+
+struct combined {
+ struct prime prm;
+ struct fibonacci fib;
+ int cco_state;
+};
+
+int combined(struct combined* g) {
+ cco_routine(g) {
+ cco_await_call(prime(&g->prm));
+ cco_await_call(fibonacci(&g->fib));
+
+ // Reuse the g->prm context and extend the count:
+ g->prm.count = 8, g->prm.result += 2;
+ cco_reset(&g->prm);
+ cco_await_call(prime(&g->prm));
+
+ cco_final:
+ puts("final combined");
+ }
+ return 0;
+}
+
+int main(void)
+{
+ struct combined c = {.prm={.count=8}, .fib={14}};
+ int res;
+
+ cco_blocking_call(res = combined(&c)) {
+ if (res == CCO_YIELD)
+ printf("Prime(%d)=%lld, Fib(%d)=%lld\n",
+ c.prm.idx, c.prm.result,
+ c.fib.idx, c.fib.result);
+ }
+}