summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/stc/algo/ccoro.h15
-rw-r--r--misc/examples/cofib.c43
-rw-r--r--misc/examples/cosub.c65
3 files changed, 73 insertions, 50 deletions
diff --git a/include/stc/algo/ccoro.h b/include/stc/algo/ccoro.h
index f5c682e8..07f98bf4 100644
--- a/include/stc/algo/ccoro.h
+++ b/include/stc/algo/ccoro.h
@@ -67,20 +67,21 @@ int main(void) {
} \
*_state = -2
-#define ccoro_yield(...) c_MACRO_OVERLOAD(ccoro_yield, __VA_ARGS__)
-#define ccoro_yield_1(value) \
+#define ccoro_yield(ret) \
do { \
- *_state = __LINE__; return value; \
+ *_state = __LINE__; return ret; \
case __LINE__:; \
} while (0)
-#define ccoro_yield_2(subcoro, c) \
+#define ccoro_yield_call(...) c_MACRO_OVERLOAD(ccoro_yield_call, __VA_ARGS__)
+#define ccoro_yield_call_2(c, subcoro) ccoro_yield_call_3(c, subcoro, )
+#define ccoro_yield_call_3(c, subcoro, ret) \
do { \
*_state = __LINE__; \
- c_PASTE(coro, __LINE__): \
- return subcoro; \
+ c_PASTE(co, __LINE__): \
+ subcoro; return ret; \
case __LINE__:; \
- if (ccoro_alive(c)) goto c_PASTE(coro, __LINE__); \
+ if (ccoro_alive(c)) goto c_PASTE(co, __LINE__); \
} while (0)
#define ccoro_final case -1
diff --git a/misc/examples/cofib.c b/misc/examples/cofib.c
deleted file mode 100644
index b58775ae..00000000
--- a/misc/examples/cofib.c
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <stc/algo/ccoro.h>
-#include <stdio.h>
-#include <stdint.h>
-
-// Use coroutine to create a fibonacci sequence generator:
-
-typedef long long llong;
-struct fibonacci {
- int n;
- int ccoro_state;
- llong a, b, idx;
-};
-
-llong fibonacci(struct fibonacci* U) {
- assert (U->n < 95);
-
- ccoro_execute(U,
- U->a = 0;
- U->b = 1;
- for (U->idx = 0; U->idx < U->n; U->idx++) {
- ccoro_yield (U->a);
- llong sum = U->a + U->b; // NB! locals only lasts until next ccoro_yield!
- U->a = U->b;
- U->b = sum;
- }
- ccoro_final:
- );
-
- return -1;
-}
-
-
-int main(void) {
- printf("Fibonacci numbers:\n");
- struct fibonacci fib = {.n = 14};
-
- for (;;) {
- llong x = fibonacci(&fib);
- if (!ccoro_alive(&fib)) break;
- printf(" %lld", x);
- }
- puts("");
-}
diff --git a/misc/examples/cosub.c b/misc/examples/cosub.c
new file mode 100644
index 00000000..0aee7aee
--- /dev/null
+++ b/misc/examples/cosub.c
@@ -0,0 +1,65 @@
+#include <stc/algo/ccoro.h>
+#include <stdio.h>
+#include <stdint.h>
+
+// Use coroutine to create a fibonacci sequence generator:
+
+typedef long long intll_t;
+
+struct fibonacci {
+ int n;
+ int ccoro_state;
+ intll_t a, b, idx;
+};
+
+intll_t fibonacci(struct fibonacci* F) {
+ assert (F->n < 95);
+
+ ccoro_execute(F,
+ F->a = 0;
+ F->b = 1;
+ for (F->idx = 0; F->idx < F->n; F->idx++) {
+ ccoro_yield (F->a);
+ intll_t sum = F->a + F->b; // NB! locals only lasts until next ccoro_yield!
+ F->a = F->b;
+ F->b = sum;
+ }
+ ccoro_final:
+ );
+
+ return -1;
+}
+
+// Demonstrate to call another coroutine from a coroutine:
+// Create a 2D iterator, and call fibonacci sequence when x,y = 1,1:
+
+struct iterate {
+ int max_x, max_y;
+ int ccoro_state;
+ int x, y;
+};
+
+bool iterate(struct iterate* I, struct fibonacci* F) {
+ ccoro_execute(I,
+ for (I->x = 0; I->x < I->max_x; I->x++)
+ for (I->y = 0; I->y < I->max_y; I->y++)
+ if (I->x == 1 && I->y == 1)
+ ccoro_yield_call (F, fibonacci(F), true);
+ else
+ ccoro_yield (true);
+ ccoro_finish:
+ );
+ return false;
+}
+
+
+int main(void) {
+ printf("Fibonacci numbers:\n");
+ struct fibonacci fib = {.n = 14};
+ struct iterate iter = {3, 3};
+
+ while (iterate(&iter, &fib))
+ printf("%d %d. Fib: %lld\n", iter.x, iter.y, fib.a);
+
+ puts("");
+}