summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-05-08 11:14:03 +0200
committerTyge Løvset <[email protected]>2023-05-08 11:14:03 +0200
commitb909bee0e400fa12908bc3d9bca447ea2a71864b (patch)
tree32dfce3fab606e8f163d13fafe3815614537bc1a
parentbca31bb8d85d6781f0c3d074eb1a25fa6de48e07 (diff)
downloadSTC-modified-b909bee0e400fa12908bc3d9bca447ea2a71864b.tar.gz
STC-modified-b909bee0e400fa12908bc3d9bca447ea2a71864b.zip
More coroutine updates.
-rw-r--r--docs/ccommon_api.md7
-rw-r--r--include/stc/algo/coroutine.h53
-rw-r--r--misc/examples/coroutines.c12
3 files changed, 42 insertions, 30 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index c20043f8..daf21e56 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -314,7 +314,7 @@ bool triples(struct triples* i) { // coroutine
}
}
}
- cco_final: // required for cleanup
+ cco_final: // tear down
puts("done");
cco_end(true);
}
@@ -363,6 +363,8 @@ To resume the coroutine from where it was suspended with *cco_yield()*, simply c
| | `cco_yield(retval)` | Suspend execution and return retval |
| | `cco_await(promise)` | Suspend until promise is true |
| | `cco_await(promise, retval)` | Suspend with retval until promise is true |
+| | `cco_call(ctx, corocall)` | Call coro async, suspend while not done |
+| | `cco_call(ctx, corocall, retval)` | Call coro async, return retval on suspend |
| | Semaphores: | |
| | `csem` | Semaphore type |
| | `cco_await_sem(sem)` | Await for the semaphore count > 0 |
@@ -373,13 +375,14 @@ To resume the coroutine from where it was suspended with *cco_yield()*, simply c
| | `ctimer` | Timer type |
| | `cco_await_timer(tm)` | Await for timer to expire |
| | `cco_await_timer(tm, retval)` | Await with retval for timer to expire |
-| | `ctimer_start(tm, long msecs)` | Start timer for milliseconds |
+| | `ctimer_start(tm, long msecs)` | Start timer msecs milliseconds |
| | `ctimer_restart(tm)` | Restart timer with same duration |
| `bool` | `ctimer_expired(tm)` | Return true if timer is expired |
| `long` | `ctimer_remaining(tm)` | Return milliseconds remaining |
| | From caller side: | |
| `void` | `cco_stop(ctx)` | Next call of coroutine returns `cco_end()` |
| `void` | `cco_reset(ctx)` | Reset state to initial (for reuse) |
+| `void` | `cco_run_blocked(ctx, corocall) { }` | Call coro blocked until done |
---
## RAII scope macros
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index 80b96bbd..942abc5a 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -62,12 +62,12 @@ enum {
cco_state_done = -2,
};
-#define cco_initial(ctx) ((ctx)->cco_state == 0)
-#define cco_suspended(ctx) ((ctx)->cco_state > 0)
-#define cco_done(ctx) ((ctx)->cco_state == cco_state_done)
+#define cco_initial(co) ((co)->cco_state == 0)
+#define cco_suspended(co) ((co)->cco_state > 0)
+#define cco_done(co) ((co)->cco_state == cco_state_done)
-#define cco_begin(ctx) \
- int *_state = &(ctx)->cco_state; \
+#define cco_begin(co) \
+ int *_state = &(co)->cco_state; \
goto _begin; _begin: switch (*_state) { \
case 0:
@@ -90,21 +90,30 @@ enum {
case __LINE__: if (!(promise)) return retval; \
} while (0)
+#define cco_call(...) c_MACRO_OVERLOAD(cco_call, __VA_ARGS__)
+#define cco_call_2(co, call) cco_call_3(co, call, )
+#define cco_call_3(co, call, retval) cco_await_2((call, cco_done(co)), retval)
+
+#define cco_run_blocked(co, call) while (call, !cco_done(co))
+
#define cco_final \
case cco_state_final
#define cco_return \
do { *_state = cco_state_final; goto _begin; } while (0)
-#define cco_stop(ctx) \
+#define cco_return_v(value) \
+ return (*_state = cco_state_final, value)
+
+#define cco_stop(co) \
do { \
- int* _state = &(ctx)->cco_state; \
+ int* _state = &(co)->cco_state; \
if (*_state > 0) *_state = cco_state_final; \
} while (0)
-#define cco_reset(ctx) \
+#define cco_reset(co) \
do { \
- int* _state = &(ctx)->cco_state; \
+ int* _state = &(co)->cco_state; \
if (*_state == cco_state_done) *_state = 0; \
} while (0)
@@ -151,28 +160,28 @@ typedef struct {
} ctimer;
#define cco_await_timer(...) c_MACRO_OVERLOAD(cco_await_timer, __VA_ARGS__)
-#define cco_await_timer_2(t, msecs) cco_await_timer_3(t, msecs, )
-#define cco_await_timer_3(t, msecs, ret) \
+#define cco_await_timer_2(tm, msecs) cco_await_timer_3(tm, msecs, )
+#define cco_await_timer_3(tm, msecs, ret) \
do { \
- ctimer_start(t, msecs); \
- cco_await_2(ctimer_expired(t), ret); \
+ ctimer_start(tm, msecs); \
+ cco_await_2(ctimer_expired(tm), ret); \
} while (0)
-static inline void ctimer_start(ctimer* t, long msecs) {
- t->interval = msecs*(CLOCKS_PER_SEC/1000);
- t->start = clock();
+static inline void ctimer_start(ctimer* tm, long msecs) {
+ tm->interval = msecs*(CLOCKS_PER_SEC/1000);
+ tm->start = clock();
}
-static inline void ctimer_restart(ctimer* t) {
- t->start = clock();
+static inline void ctimer_restart(ctimer* tm) {
+ tm->start = clock();
}
-static inline bool ctimer_expired(ctimer* t) {
- return clock() - t->start >= t->interval;
+static inline bool ctimer_expired(ctimer* tm) {
+ return clock() - tm->start >= tm->interval;
}
-static inline long ctimer_remaining(ctimer* t) {
- return (long)((double)(t->start + t->interval - clock())*(1000.0/CLOCKS_PER_SEC));
+static inline long ctimer_remaining(ctimer* tm) {
+ return (long)((double)(tm->start + tm->interval - clock())*(1000.0/CLOCKS_PER_SEC));
}
#endif
diff --git a/misc/examples/coroutines.c b/misc/examples/coroutines.c
index 9071fee0..7f255dda 100644
--- a/misc/examples/coroutines.c
+++ b/misc/examples/coroutines.c
@@ -81,26 +81,26 @@ struct combined {
};
-bool combined(struct combined* g) {
+void combined(struct combined* g) {
cco_begin(g);
- cco_await(prime(&g->prm), false);
- cco_await(fibonacci(&g->fib), false);
+ cco_await(prime(&g->prm));
+ cco_await(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(prime(&g->prm), false);
+ cco_await(prime(&g->prm));
cco_final:
puts("final combined");
- cco_end(true);
+ cco_end();
}
int main(void)
{
struct combined c = {.prm={.count=8}, .fib={14}};
- while (!combined(&c)) {
+ cco_run_blocked(&c, combined(&c)) {
printf("Prime(%d)=%lld, Fib(%d)=%lld\n",
c.prm.idx, c.prm.result,
c.fib.idx, c.fib.result);