summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/ccommon_api.md8
-rw-r--r--include/stc/algo/coroutine.h14
-rw-r--r--misc/examples/cointerleave.c8
-rw-r--r--misc/examples/coread.c8
-rw-r--r--misc/examples/coroutines.c6
-rw-r--r--misc/examples/generator.c32
-rw-r--r--misc/examples/scheduler.c2
-rw-r--r--misc/examples/triples.c46
8 files changed, 61 insertions, 63 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 7014def8..2319109b 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -314,7 +314,7 @@ bool triples(struct triples* i) { // coroutine
}
}
}
- cco_final: // required label
+ cco_final: // required for cleanup
puts("done");
cco_end(true);
}
@@ -352,15 +352,15 @@ To resume the coroutine from where it was suspended with *cco_yield()*, simply c
| | Function / operator | Description |
|:----------|:-------------------------------------|:----------------------------------------|
-| | `cco_final:` | Obligatory label in coroutine |
+| | `cco_final:` | Label for cleanup in coroutine |
| | `cco_return` | Early return from the coroutine (no arg) |
| `bool` | `cco_suspended(ctx)` | Is coroutine in suspended state? |
| `bool` | `cco_done(ctx)` | Is coroutine done? |
| | `cco_begin(ctx)` | Begin coroutine block |
-| | `cco_end(retval)` | End coroutine block and return retval |
| | `cco_end()` | End coroutine block |
-| | `cco_yield(retval)` | Suspend execution and return retval |
+| | `cco_end(retval)` | End coroutine block and return retval |
| | `cco_yield()` | Suspend execution |
+| | `cco_yield(retval)` | Suspend execution and return retval |
| | `cco_await(promise)` | Suspend until promise is true |
| | `cco_await_with(promise, retval)` | Suspend with retval until promise is true |
| | Semaphores: | |
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index 89dd27f0..c9cb8fc0 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -38,7 +38,7 @@ bool coroutine(struct coroutine* I) {
for (I->y = 0; I->y < I->max_y; I->y++)
cco_yield(false);
- cco_final:
+ cco_final: // required if there is cleanup code
puts("final");
cco_end(true);
}
@@ -68,13 +68,12 @@ enum {
#define cco_begin(ctx) \
int *_state = &(ctx)->cco_state; \
- switch (*_state) { \
+ goto _begin; _begin: switch (*_state) { \
case 0:
#define cco_end(retval) \
- *_state = cco_state_done; break; \
- case -99: goto _cco_final_; \
} \
+ *_state = cco_state_done; \
return retval
#define cco_yield(retval) \
@@ -92,11 +91,10 @@ enum {
} while (0)
#define cco_final \
- case cco_state_final: \
- _cco_final_
+ case cco_state_final
#define cco_return \
- goto _cco_final_
+ do { *_state = cco_state_final; goto _begin; } while (0)
#define cco_stop(ctx) \
do { \
@@ -112,7 +110,7 @@ enum {
typedef struct {
- int count;
+ intptr_t count;
} cco_semaphore;
/**
diff --git a/misc/examples/cointerleave.c b/misc/examples/cointerleave.c
index 5bdbd257..4fe89316 100644
--- a/misc/examples/cointerleave.c
+++ b/misc/examples/cointerleave.c
@@ -16,7 +16,6 @@ static int next_value(struct GenValue* g)
cco_begin(g);
for (g->it = IVec_begin(g->v); g->it.ref; IVec_next(&g->it))
cco_yield(*g->it.ref);
- cco_final:
cco_end(0);
}
@@ -37,7 +36,6 @@ void interleaved(struct Generator* g)
g->value = next_value(&g->y);
if (!cco_done(&g->y)) cco_yield();
}
- cco_final:
cco_end();
}
@@ -48,9 +46,11 @@ void Use(void)
struct Generator g = {{&a}, {&b}};
- while (interleaved(&g), !cco_done(&g))
+ while (1) {
+ interleaved(&g);
+ if (cco_done(&g)) break;
printf("%d ", g.value);
-
+ }
puts("");
c_drop(IVec, &a, &b);
}
diff --git a/misc/examples/coread.c b/misc/examples/coread.c
index 38447c44..0073191b 100644
--- a/misc/examples/coread.c
+++ b/misc/examples/coread.c
@@ -20,10 +20,10 @@ bool file_read(struct file_read* g)
while (cstr_getline(&g->line, g->fp))
cco_yield(false);
- cco_final: // this label is required.
- printf("finish\n");
- cstr_drop(&g->line);
- fclose(g->fp);
+ cco_final:
+ printf("finish\n");
+ cstr_drop(&g->line);
+ fclose(g->fp);
cco_end(true);
}
diff --git a/misc/examples/coroutines.c b/misc/examples/coroutines.c
index a5db3291..9071fee0 100644
--- a/misc/examples/coroutines.c
+++ b/misc/examples/coroutines.c
@@ -35,7 +35,7 @@ bool prime(struct prime* g) {
cco_yield(false);
}
}
- cco_final:
+ cco_final:
printf("final prm\n");
cco_end(true);
}
@@ -67,7 +67,7 @@ bool fibonacci(struct fibonacci* g) {
}
cco_yield(false);
}
- cco_final:
+ cco_final:
printf("final fib\n");
cco_end(true);
}
@@ -91,7 +91,7 @@ bool combined(struct combined* g) {
cco_reset(&g->prm);
cco_await(prime(&g->prm), false);
- cco_final:
+ cco_final:
puts("final combined");
cco_end(true);
}
diff --git a/misc/examples/generator.c b/misc/examples/generator.c
index 2bccc489..41dffafb 100644
--- a/misc/examples/generator.c
+++ b/misc/examples/generator.c
@@ -4,37 +4,38 @@
#include <stdio.h>
typedef struct {
- int n;
+ int size;
int a, b, c;
-} Triple_value, Triple;
+} Triple, Triple_value;
typedef struct {
Triple_value* ref;
+ int count;
int cco_state;
} Triple_iter;
-bool Triple_next(Triple_iter* it) {
+void Triple_next(Triple_iter* it) {
Triple_value* t = it->ref;
cco_begin(it);
- for (t->c = 1;; ++t->c) {
+ for (t->c = 5; t->size; ++t->c) {
for (t->a = 1; t->a < t->c; ++t->a) {
for (t->b = t->a; t->b < t->c; ++t->b) {
if (t->a*t->a + t->b*t->b == t->c*t->c) {
- if (t->n-- == 0) cco_return;
- cco_yield(true);
+ if (it->count++ == t->size)
+ cco_return;
+ cco_yield();
}
}
}
}
- cco_final:
- it->ref = NULL;
- cco_end(false);
+ cco_final:
+ it->ref = NULL;
+ cco_end();
}
Triple_iter Triple_begin(Triple* t) {
- Triple_iter it = {t};
- if (t->n > 0) Triple_next(&it);
- else it.ref = NULL;
+ Triple_iter it = {.ref=t};
+ Triple_next(&it);
return it;
}
@@ -42,11 +43,10 @@ Triple_iter Triple_begin(Triple* t) {
int main()
{
puts("Pythagorean triples with c < 100:");
- Triple t = {INT32_MAX};
- c_foreach (i, Triple, t)
- {
+ Triple triple = {.size=30}; // max number of triples
+ c_foreach (i, Triple, triple) {
if (i.ref->c < 100)
- printf("%u: (%d, %d, %d)\n", INT32_MAX - i.ref->n + 1, i.ref->a, i.ref->b, i.ref->c);
+ printf("%u: (%d, %d, %d)\n", i.count, i.ref->a, i.ref->b, i.ref->c);
else
cco_stop(&i);
}
diff --git a/misc/examples/scheduler.c b/misc/examples/scheduler.c
index db9c2716..04107d5e 100644
--- a/misc/examples/scheduler.c
+++ b/misc/examples/scheduler.c
@@ -42,7 +42,6 @@ static bool taskA(struct Task* task)
puts("A is back doing more work");
cco_yield(resume_task(task));
puts("A is back doing even more work");
- cco_final:
cco_end(true);
}
@@ -54,7 +53,6 @@ static bool taskB(struct Task* task)
puts("B is back doing work");
cco_yield(resume_task(task));
puts("B is back doing more work");
- cco_final:
cco_end(true);
}
diff --git a/misc/examples/triples.c b/misc/examples/triples.c
index 2e0211c3..183b7389 100644
--- a/misc/examples/triples.c
+++ b/misc/examples/triples.c
@@ -3,12 +3,21 @@
#include <stc/algo/coroutine.h>
#include <stdio.h>
+int gcd(int a, int b) {
+ while (b) {
+ int t = a % b;
+ a = b;
+ b = t;
+ }
+ return a;
+}
+
void triples_vanilla(int n) {
- for (int c = 5; n; ++c) {
+ for (int c = 5, i = 0; n; ++c) {
for (int a = 1; a < c; ++a) {
for (int b = a + 1; b < c; ++b) {
- if ((int64_t)a*a + (int64_t)b*b == (int64_t)c*c) {
- printf("{%d, %d, %d}\n", a, b, c);
+ if ((int64_t)a*a + (int64_t)b*b == (int64_t)c*c && gcd(a, b) == 1) {
+ printf("%d: {%d, %d, %d}\n", ++i, a, b, c);
if (--n == 0) goto done;
}
}
@@ -18,41 +27,34 @@ void triples_vanilla(int n) {
}
struct triples {
- int n;
+ int size, count;
int a, b, c;
int cco_state;
};
-bool triples_coro(struct triples* I) {
- cco_begin(I);
- for (I->c = 5; I->n; ++I->c) {
- for (I->a = 1; I->a < I->c; ++I->a) {
- for (I->b = I->a + 1; I->b < I->c; ++I->b) {
- if ((int64_t)I->a*I->a + (int64_t)I->b*I->b == (int64_t)I->c*I->c) {
+bool triples_coro(struct triples* t) {
+ cco_begin(t);
+ t->count = 0;
+ for (t->c = 5; t->size; ++t->c) {
+ for (t->a = 1; t->a < t->c; ++t->a) {
+ for (t->b = t->a + 1; t->b < t->c; ++t->b) {
+ if ((int64_t)t->a*t->a + (int64_t)t->b*t->b == (int64_t)t->c*t->c) {
+ if (t->count++ == t->size)
+ cco_return;
cco_yield(false);
- if (--I->n == 0) cco_return;
}
}
}
}
- cco_final:
+ cco_final:
puts("done");
cco_end(true);
}
-int gcd(int a, int b) {
- while (b) {
- int t = a % b;
- a = b;
- b = t;
- }
- return a;
-}
-
int main()
{
puts("Vanilla triples:");
- triples_vanilla(6);
+ triples_vanilla(5);
puts("\nCoroutine triples:");
struct triples t = {INT32_MAX};