summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-05-08 13:23:05 +0200
committerTyge Løvset <[email protected]>2023-05-08 13:23:05 +0200
commitf8f544d8f5b805b9749f1e06fd7c1875b6115d48 (patch)
treefbcb7f3ec9799bf537b8a8cc0ea014c7da398538
parentb909bee0e400fa12908bc3d9bca447ea2a71864b (diff)
downloadSTC-modified-f8f544d8f5b805b9749f1e06fd7c1875b6115d48.tar.gz
STC-modified-f8f544d8f5b805b9749f1e06fd7c1875b6115d48.zip
Final coroutine API updates.
-rw-r--r--docs/ccommon_api.md34
-rw-r--r--include/stc/algo/coroutine.h27
-rw-r--r--misc/examples/cointerleave.c13
3 files changed, 38 insertions, 36 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index daf21e56..fb29d642 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -354,35 +354,37 @@ To resume the coroutine from where it was suspended with *cco_yield()*, simply c
|:----------|:-------------------------------------|:----------------------------------------|
| | `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 |
+| `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(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(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 |
+| | `cco_end(ret)` | End coroutine block and return ret |
+| | `cco_yield()` | Yield/suspend execution |
+| | `cco_yield(ret)` | Yield/suspend execution and return ret |
+| | `cco_yield_sub(subco, call)` | Yield if subco not done after call |
+| | `cco_yield_sub(subco, call, ret)` | Yield with ret if subco alive after call |
+| | `cco_await(promise)` | Wait/suspend until promise is true |
+| | `cco_await(promise, ret)` | Wait/suspend with ret value |
+| | `cco_await_sub(subco, call)` | Wait/suspend until subco call is done |
+| | `cco_await_sub(subco, call, ret)` | Wait/suspend with ret on subco call done |
| | Semaphores: | |
| | `csem` | Semaphore type |
| | `cco_await_sem(sem)` | Await for the semaphore count > 0 |
-| | `cco_await_sem(sem, retval)` | Await with retval for the semaphore |
-| | `csem_set(sem, long value)` | Set semaphore |
+| | `cco_await_sem(sem, ret)` | Await with ret on the semaphore |
+| | `csem_set(sem, long value)` | Set semaphore value |
| | `csem_signal(sem)` | Signal the semaphore |
| | Timers: | |
| | `ctimer` | Timer type |
| | `cco_await_timer(tm)` | Await for timer to expire |
-| | `cco_await_timer(tm, retval)` | Await with retval for timer to expire |
+| | `cco_await_timer(tm, ret)` | Await with ret for timer to expire |
| | `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 |
+| `void` | `cco_stop(co)` | Next call of coroutine returns `cco_end()` |
+| `void` | `cco_reset(co)` | Reset state to initial (for reuse) |
+| `void` | `cco_run_blocked(co, corocall) { }` | Call coro blocked until done |
---
## RAII scope macros
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index 942abc5a..83814605 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -71,28 +71,33 @@ enum {
goto _begin; _begin: switch (*_state) { \
case 0:
-#define cco_end(retval) \
+#define cco_end(ret) \
} \
*_state = cco_state_done; \
- return retval
+ return ret
-#define cco_yield(retval) \
+#define cco_yield(ret) \
do { \
- *_state = __LINE__; return retval; \
+ *_state = __LINE__; return ret; \
case __LINE__:; \
} while (0)
+#define cco_yield_sub(...) c_MACRO_OVERLOAD(cco_yield_sub, __VA_ARGS__)
+#define cco_yield_sub_2(co, call) cco_yield_sub_3(co, call, )
+#define cco_yield_sub_3(co, call, ret) \
+ do { call; if (!cco_done(co)) cco_yield(ret); } while (0)
+
#define cco_await(...) c_MACRO_OVERLOAD(cco_await, __VA_ARGS__)
#define cco_await_1(promise) cco_await_2(promise, )
-#define cco_await_2(promise, retval) \
+#define cco_await_2(promise, ret) \
do { \
*_state = __LINE__; \
- case __LINE__: if (!(promise)) return retval; \
+ case __LINE__: if (!(promise)) return ret; \
} 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_await_sub(...) c_MACRO_OVERLOAD(cco_await_sub, __VA_ARGS__)
+#define cco_await_sub_2(co, call) cco_await_sub_3(co, call, )
+#define cco_await_sub_3(co, call, ret) cco_await_2((call, cco_done(co)), ret)
#define cco_run_blocked(co, call) while (call, !cco_done(co))
@@ -127,9 +132,9 @@ typedef struct {
#define cco_await_sem(...) c_MACRO_OVERLOAD(cco_await_sem, __VA_ARGS__)
#define cco_await_sem_1(sem) cco_await_sem_2(sem, )
-#define cco_await_sem_2(sem, retval) \
+#define cco_await_sem_2(sem, ret) \
do { \
- cco_await_2((sem)->count > 0, retval); \
+ cco_await_2((sem)->count > 0, ret); \
--(sem)->count; \
} while (0)
diff --git a/misc/examples/cointerleave.c b/misc/examples/cointerleave.c
index 4fe89316..0ccf9ad7 100644
--- a/misc/examples/cointerleave.c
+++ b/misc/examples/cointerleave.c
@@ -11,7 +11,7 @@ struct GenValue {
int cco_state;
};
-static int next_value(struct GenValue* g)
+static int get_value(struct GenValue* g)
{
cco_begin(g);
for (g->it = IVec_begin(g->v); g->it.ref; IVec_next(&g->it))
@@ -30,11 +30,8 @@ void interleaved(struct Generator* g)
cco_begin(g);
while (!cco_done(&g->x) || !cco_done(&g->y))
{
- g->value = next_value(&g->x);
- if (!cco_done(&g->x)) cco_yield();
-
- g->value = next_value(&g->y);
- if (!cco_done(&g->y)) cco_yield();
+ cco_yield_sub(&g->x, g->value = get_value(&g->x));
+ cco_yield_sub(&g->y, g->value = get_value(&g->y));
}
cco_end();
}
@@ -46,9 +43,7 @@ void Use(void)
struct Generator g = {{&a}, {&b}};
- while (1) {
- interleaved(&g);
- if (cco_done(&g)) break;
+ cco_run_blocked(&g, interleaved(&g)) {
printf("%d ", g.value);
}
puts("");