summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/stc/algo/coroutine.h35
-rw-r--r--misc/examples/coread.c6
-rw-r--r--misc/examples/coroutines.c11
3 files changed, 23 insertions, 29 deletions
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index 6e36750d..da15aa5b 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -35,40 +35,41 @@ struct iterate {
int y;
};
-bool iterate(struct iterate* U) {
- cco_begin(U);
- for (U->x = 0; U->x < U->max_x; U->x++)
- for (U->y = 0; U->y < U->max_y; U->y++)
- cco_yield (true);
+bool iterate(struct iterate* I) {
+ cco_begin(I);
+ for (I->x = 0; I->x < I->max_x; I->x++)
+ for (I->y = 0; I->y < I->max_y; I->y++)
+ cco_yield(true);
cco_final:
puts("final");
- cco_end(U);
- return false;
+ cco_end(false);
}
int main(void) {
- struct iterate it = {3, 3};
+ struct iterate it = {.max_x=3, .max_y=3};
int n = 0;
while (iterate(&it))
{
printf("%d %d\n", it.x, it.y);
- if (++n == 20) { iterate(cco_stop(&it)); break; }
+ // example of early stop:
+ if (++n == 20) (void)cco_stop(&it); // signal to stop at next
}
return 0;
}
*/
#include <stc/ccommon.h>
-#define cco_begin(c) \
- int *_state = &(c)->cco_state; \
+#define cco_begin(ctx) \
+ int *_state = &(ctx)->cco_state; \
switch (*_state) { \
case 0:
-#define cco_end() \
+#define cco_end(retval) \
*_state = 0; break; \
default: assert(!"missing cco_final: or illegal state"); \
- }
+ } \
+ return retval
#define cco_yield(retval) \
do { \
@@ -76,15 +77,15 @@ int main(void) {
case __LINE__:; \
} while (0)
-#define cco_yield_coroutine(c, corocall, retval) \
+#define cco_yield_coroutine(ctx, corocall, retval) \
do { \
*_state = __LINE__; \
c_PASTE(cco, __LINE__): corocall; return retval; \
- case __LINE__:; if (cco_alive(c)) goto c_PASTE(cco, __LINE__); \
+ case __LINE__:; if (cco_alive(ctx)) goto c_PASTE(cco, __LINE__); \
} while (0)
#define cco_final case -1
-#define cco_alive(c) ((c) && (c)->cco_state > 0)
-#define cco_stop(c) ((c)->cco_state = ((c)->cco_state > 0 ? -1 : -2), c)
+#define cco_alive(ctx) ((ctx)->cco_state > 0)
+#define cco_stop(ctx) ((ctx)->cco_state = cco_alive(ctx) ? -1 : -2), ctx)
#endif
diff --git a/misc/examples/coread.c b/misc/examples/coread.c
index 3d49c5df..4df80339 100644
--- a/misc/examples/coread.c
+++ b/misc/examples/coread.c
@@ -24,8 +24,7 @@ bool file_nextline(struct file_nextline* U)
printf("finish\n");
cstr_drop(&U->line);
fclose(U->fp);
- cco_end();
- return false;
+ cco_end(false);
}
int main(void) {
@@ -33,9 +32,6 @@ int main(void) {
int n = 0;
while (file_nextline(&z)) {
printf("%3d %s\n", ++n, cstr_str(&z.line));
-
- // stop after 15 lines:
- if (n == 15) (void)cco_stop(&z);
}
printf("state %d\n", z.cco_state);
}
diff --git a/misc/examples/coroutines.c b/misc/examples/coroutines.c
index 5d2a178a..89b428ee 100644
--- a/misc/examples/coroutines.c
+++ b/misc/examples/coroutines.c
@@ -17,8 +17,7 @@ bool iterate(struct iterate* I) {
for (I->y = 0; I->y < I->max_y; I->y++)
cco_yield(true);
cco_final:
- cco_end();
- return false;
+ cco_end(false);
}
// Use coroutine to create a fibonacci sequence generator:
@@ -42,9 +41,7 @@ int64_t fibonacci(struct fibonacci* F) {
F->b = sum;
}
cco_final:
- cco_end();
-
- return -1;
+ cco_end(-1);
}
// Combine
@@ -60,10 +57,10 @@ bool combine(struct combine* C) {
cco_yield_coroutine(&C->it, iterate(&C->it), true);
cco_yield_coroutine(&C->fib, fibonacci(&C->fib), true);
// May reuse the C->it context; state has been reset to 0.
+ C->it.max_x = 2; C->it.max_y = 2;
cco_yield_coroutine(&C->it, iterate(&C->it), true);
cco_final: puts("final");
- cco_end();
- return false;
+ cco_end(false);
}
int main(void) {