summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-05-24 16:21:22 +0200
committerTyge Løvset <[email protected]>2023-05-24 16:21:22 +0200
commit276b8110033aa275f58ce60d096f220ca050738c (patch)
tree76f5e2c069ecbe268c5497fafafb3b4cb7e66a51
parent8a19b4d6ff098ec014244c86569a7bea2db65514 (diff)
downloadSTC-modified-276b8110033aa275f58ce60d096f220ca050738c.tar.gz
STC-modified-276b8110033aa275f58ce60d096f220ca050738c.zip
coroutine.h:
- Renamed Liigo's coroutine macro cco(x) => cco_routine(x). - Removed cco_begin(x), cco_end() macros. Replaced by cco_routine(x). - Replaced csleep_ms() with csleep_us(), using select() which is portable. - Updated all coroutine examples.
-rw-r--r--docs/ccommon_api.md11
-rw-r--r--include/stc/algo/coroutine.h49
-rw-r--r--misc/examples/cointerleave.c11
-rw-r--r--misc/examples/coread.c3
-rw-r--r--misc/examples/coroutines.c14
-rw-r--r--misc/examples/generator.c21
-rw-r--r--misc/examples/scheduler.c10
-rw-r--r--misc/examples/triples.c5
8 files changed, 58 insertions, 66 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 5f6c82ed..beaad7e9 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -321,7 +321,7 @@ struct triples {
};
bool triples(struct triples* i) { // coroutine
- cco_begin(i);
+ cco_routine(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) {
@@ -332,9 +332,10 @@ bool triples(struct triples* i) { // coroutine
}
}
}
- cco_final: // tear down
+ cco_final:
puts("done");
- cco_end(true);
+ }
+ return true;
}
int gcd(int a, int b) { // greatest common denominator
@@ -374,9 +375,7 @@ To resume the coroutine from where it was suspended with *cco_yield()*, simply c
| | `cco_return` | Early return from the coroutine (no arg) |
| `bool` | `cco_suspended(co)` | Is coroutine in suspended state? |
| `bool` | `cco_done(co)` | Is coroutine done? |
-| | `cco_begin(co)` | Begin coroutine block |
-| | `cco_end()` | End coroutine block |
-| | `cco_end(ret)` | End coroutine block and return ret |
+| | `cco_routine(co) { ... }` | The coroutine closure |
| | `cco_yield()` | Yield/suspend execution |
| | `cco_yield(ret)` | Yield/suspend execution and return ret |
| | `cco_yield_coro(co, call)` | Yield at co call if it is suspended |
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index 78dc80c6..ebfed613 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -26,31 +26,32 @@
#include <stdio.h>
#include <stc/algo/coroutine.h>
-struct coroutine {
+struct iterpair {
int max_x, max_y;
int x, y;
int cco_state; // required member
};
-bool coroutine(struct coroutine* I) {
- cco_begin(I);
+bool iterpair(struct iterpair* I) {
+ cco_routine(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(false);
- cco_final: // required if there is cleanup code
+ cco_final: // required if there is cleanup code
puts("final");
- cco_end(true);
+ }
+ return true; // finished
}
int main(void) {
- struct coroutine it = {.max_x=3, .max_y=3};
+ struct iterpair it = {.max_x=3, .max_y=3};
int n = 0;
- while (!coroutine(&it))
+ while (!iterpair(&it))
{
printf("%d %d\n", it.x, it.y);
// example of early stop:
- if (++n == 7) cco_stop(&it); // signal to stop at next
+ if (++n == 7) cco_stop(&it); // signal to stop/finalize in next
}
return 0;
}
@@ -66,19 +67,9 @@ enum {
#define cco_suspended(co) ((co)->cco_state > 0)
#define cco_done(co) ((co)->cco_state == cco_state_done)
-#define cco_begin(co) \
- int *_state = &(co)->cco_state; \
- goto _begin; _begin: switch (*_state) { \
- case 0:
-
-#define cco_end(ret) \
- } \
- *_state = cco_state_done; \
- return ret
-
-#define cco(co) \
+#define cco_routine(co) \
for (int *_state = &(co)->cco_state, _once=1; _once; *_state = cco_state_done, _once=0) \
- _begin: switch (*_state) case 0:
+ _begin: switch (*_state) case 0: // thanks, @liigo!
#define cco_yield(ret) \
do { \
@@ -96,7 +87,7 @@ enum {
#define cco_await_2(promise, ret) \
do { \
*_state = __LINE__; \
- case __LINE__: if (!(promise)) return ret; \
+ case __LINE__: if (!(promise)) {return ret; goto _begin;} \
} while (0)
#define cco_await_coro(...) c_MACRO_OVERLOAD(cco_await_coro, __VA_ARGS__)
@@ -150,18 +141,12 @@ typedef struct {
*/
#include <time.h>
+#include <sys/time.h>
-#ifdef _WIN32
- static inline void csleep_ms(long msecs) {
- extern void Sleep(unsigned long);
- Sleep((unsigned long)msecs);
- }
-#elif _POSIX_C_SOURCE >= 199309L
- static inline void csleep_ms(long msecs) {
- struct timespec ts = {msecs/1000, 1000000*(msecs % 1000)};
- nanosleep(&ts, NULL);
- }
-#endif
+static inline void csleep_us(int64_t usec) {
+ struct timeval tv = {.tv_sec=(int)(usec/1000000), .tv_usec=usec % 1000000};
+ select(0, NULL, NULL, NULL, &tv);
+}
typedef struct {
clock_t start;
diff --git a/misc/examples/cointerleave.c b/misc/examples/cointerleave.c
index e11b2bf3..42bf1d32 100644
--- a/misc/examples/cointerleave.c
+++ b/misc/examples/cointerleave.c
@@ -1,6 +1,6 @@
// https://www.youtube.com/watch?v=8sEe-4tig_A
-#include <stc/calgo.h>
#include <stdio.h>
+#include <stc/calgo.h>
#define i_type IVec
#define i_val int
#include <stc/cvec.h>
@@ -13,10 +13,11 @@ struct GenValue {
static int get_value(struct GenValue* g)
{
- cco_begin(g);
+ cco_routine(g) {
for (g->it = IVec_begin(g->v); g->it.ref; IVec_next(&g->it))
cco_yield(*g->it.ref);
- cco_end(0);
+ }
+ return -1;
}
struct Generator {
@@ -27,13 +28,13 @@ struct Generator {
void interleaved(struct Generator* g)
{
- cco_begin(g);
+ cco_routine(g) {
while (!(cco_done(&g->x) & cco_done(&g->y)))
{
cco_yield_coro(&g->x, g->value = get_value(&g->x));
cco_yield_coro(&g->y, g->value = get_value(&g->y));
}
- cco_end();
+ }
}
void Use(void)
diff --git a/misc/examples/coread.c b/misc/examples/coread.c
index 1976231f..ef6cd6ee 100644
--- a/misc/examples/coread.c
+++ b/misc/examples/coread.c
@@ -1,3 +1,4 @@
+#define i_static
#include <stc/cstr.h>
#include <stc/algo/coroutine.h>
#include <errno.h>
@@ -13,7 +14,7 @@ struct file_read {
void file_read(struct file_read* g)
{
- cco(g) {
+ cco_routine(g) {
g->fp = fopen(g->filename, "r");
g->line = cstr_init();
diff --git a/misc/examples/coroutines.c b/misc/examples/coroutines.c
index a7136993..040b8472 100644
--- a/misc/examples/coroutines.c
+++ b/misc/examples/coroutines.c
@@ -19,7 +19,7 @@ struct prime {
};
bool prime(struct prime* g) {
- cco_begin(g);
+ cco_routine(g) {
if (g->result < 2) g->result = 2;
if (g->result == 2) {
if (g->count-- == 0) cco_return;
@@ -37,7 +37,8 @@ bool prime(struct prime* g) {
}
cco_final:
printf("final prm\n");
- cco_end(true);
+ }
+ return true;
}
@@ -52,7 +53,7 @@ struct fibonacci {
bool fibonacci(struct fibonacci* g) {
assert(g->count < 94);
- cco_begin(g);
+ cco_routine(g) {
g->idx = 0;
g->result = 0;
g->b = 1;
@@ -69,7 +70,8 @@ bool fibonacci(struct fibonacci* g) {
}
cco_final:
printf("final fib\n");
- cco_end(true);
+ }
+ return true;
}
// Combine
@@ -82,7 +84,7 @@ struct combined {
void combined(struct combined* g) {
- cco_begin(g);
+ cco_routine(g) {
cco_await(prime(&g->prm));
cco_await(fibonacci(&g->fib));
@@ -93,7 +95,7 @@ void combined(struct combined* g) {
cco_final:
puts("final combined");
- cco_end();
+ }
}
int main(void)
diff --git a/misc/examples/generator.c b/misc/examples/generator.c
index 41dffafb..6b4b8407 100644
--- a/misc/examples/generator.c
+++ b/misc/examples/generator.c
@@ -15,13 +15,14 @@ typedef struct {
} Triple_iter;
void Triple_next(Triple_iter* it) {
- Triple_value* t = it->ref;
- cco_begin(it);
- 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 (it->count++ == t->size)
+ Triple_value* g = it->ref;
+ cco_routine(it)
+ {
+ for (g->c = 5; g->size; ++g->c) {
+ for (g->a = 1; g->a < g->c; ++g->a) {
+ for (g->b = g->a; g->b < g->c; ++g->b) {
+ if (g->a*g->a + g->b*g->b == g->c*g->c) {
+ if (it->count++ == g->size)
cco_return;
cco_yield();
}
@@ -30,11 +31,11 @@ void Triple_next(Triple_iter* it) {
}
cco_final:
it->ref = NULL;
- cco_end();
+ }
}
-Triple_iter Triple_begin(Triple* t) {
- Triple_iter it = {.ref=t};
+Triple_iter Triple_begin(Triple* g) {
+ Triple_iter it = {.ref=g};
Triple_next(&it);
return it;
}
diff --git a/misc/examples/scheduler.c b/misc/examples/scheduler.c
index 14c85f56..ea1414c7 100644
--- a/misc/examples/scheduler.c
+++ b/misc/examples/scheduler.c
@@ -34,7 +34,7 @@ static bool push_task(const struct Task* task)
static bool taskA(struct Task* task)
{
- cco_begin(task);
+ cco_routine(task) {
puts("Hello, from task A");
cco_yield(push_task(task));
puts("A is back doing work");
@@ -42,18 +42,20 @@ static bool taskA(struct Task* task)
puts("A is back doing more work");
cco_yield(push_task(task));
puts("A is back doing even more work");
- cco_end(true);
+ }
+ return true;
}
static bool taskB(struct Task* task)
{
- cco_begin(task);
+ cco_routine(task) {
puts("Hello, from task B");
cco_yield(push_task(task));
puts("B is back doing work");
cco_yield(push_task(task));
puts("B is back doing more work");
- cco_end(true);
+ }
+ return true;
}
void Use(void)
diff --git a/misc/examples/triples.c b/misc/examples/triples.c
index 183b7389..06142916 100644
--- a/misc/examples/triples.c
+++ b/misc/examples/triples.c
@@ -33,7 +33,7 @@ struct triples {
};
bool triples_coro(struct triples* t) {
- cco_begin(t);
+ cco_routine(t) {
t->count = 0;
for (t->c = 5; t->size; ++t->c) {
for (t->a = 1; t->a < t->c; ++t->a) {
@@ -48,7 +48,8 @@ bool triples_coro(struct triples* t) {
}
cco_final:
puts("done");
- cco_end(true);
+ }
+ return true;
}
int main()