summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/ccommon_api.md16
-rw-r--r--include/stc/algo/coroutine.h29
-rw-r--r--misc/examples/cointerleave.c13
-rw-r--r--misc/examples/coroutines.c26
4 files changed, 42 insertions, 42 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index f4a2c349..7014def8 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -358,18 +358,18 @@ To resume the coroutine from where it was suspended with *cco_yield()*, simply c
| `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 (return void) |
+| | `cco_end()` | End coroutine block |
| | `cco_yield(retval)` | Suspend execution and return retval |
-| | `cco_yield()` | Suspend execution (return void) |
-| | `cco_await(promise)` | Suspend and return false until promise is true |
-| | `cco_await_void(promise)` | Suspend until promise is true (return void) |
-| | `cco_await_while(cond, retval)` | Suspend and return retval while cond is true |
+| | `cco_yield()` | Suspend execution |
+| | `cco_await(promise)` | Suspend until promise is true |
+| | `cco_await_with(promise, retval)` | Suspend with retval until promise is true |
| | Semaphores: | |
-| | `cco_semaphore` | Semaphore type |
-| | `cco_await_sem(sem)` | Await for the semaphore count > 0 |
+| | `cco_semaphore` | Semaphore type |
+| | `cco_await_sem(sem)` | Await for the semaphore count > 0 |
+| | `cco_await_sem_with(sem, retval)` | Await with retval for the semaphore |
| | `cco_signal_sem(sem)` | Signal the semaphore by increasing count|
| | From caller side: | |
-| `void` | `cco_stop(ctx)` | Next call of coroutine returns `cco_end()` |
+| `void` | `cco_stop(ctx)` | Next call of coroutine returns `cco_end()` |
| `void` | `cco_reset(ctx)` | Reset state to initial (for reuse) |
---
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index 5cadbc6a..ae9e4464 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -82,15 +82,13 @@ enum cco_states {
case __LINE__:; \
} while (0)
-#define cco_await_while(cond, retval) \
+#define cco_await(promise) cco_await_with(promise, )
+#define cco_await_with(promise, retval) \
do { \
*_state = __LINE__; \
- case __LINE__: if (cond) return retval; \
+ case __LINE__: if (!(promise)) return retval; \
} while (0)
-#define cco_await(promise) cco_await_while(!(promise), false)
-#define cco_await_void(promise) cco_await_while(!(promise), )
-
#define cco_final \
case cco_state_final: \
_cco_final_
@@ -118,22 +116,21 @@ typedef struct {
/**
* Wait for a semaphore
*
- * This macro carries out the "wait" operation on the semaphore. The
- * wait operation causes the "thread" to block while the counter is
- * zero. When the counter reaches a value larger than zero, the
- * "thread" will continue.
+ * This macro carries out the "wait" operation on the semaphore,
+ * and causes the "thread" to block while the counter is zero.
*/
-#define cco_await_sem(sem) \
- do { \
- cco_await((sem)->count > 0); \
- --(sem)->count; \
- } while (0)
+#define cco_await_sem(sem) cco_await_sem_with(sem, )
+#define cco_await_sem_with(sem, retval) \
+ do { \
+ cco_await_with((sem)->count > 0, retval); \
+ --(sem)->count; \
+ } while (0)
/**
* Signal a semaphore
*
- * This macro carries out the "signal" operation on the semaphore. The
- * signal operation increments the counter inside the semaphore, which
+ * This macro carries out the "signal" operation on the semaphore,
+ * and increments the counter inside the semaphore, which
* eventually will cause waiting "threads" to continue executing.
*/
#define cco_signal_sem(sem) ++(sem)->count
diff --git a/misc/examples/cointerleave.c b/misc/examples/cointerleave.c
index 9ef7d561..5bdbd257 100644
--- a/misc/examples/cointerleave.c
+++ b/misc/examples/cointerleave.c
@@ -26,19 +26,19 @@ struct Generator {
int value;
};
-bool interleaved(struct Generator* g)
+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(false);
+ if (!cco_done(&g->x)) cco_yield();
g->value = next_value(&g->y);
- if (!cco_done(&g->y)) cco_yield(false);
+ if (!cco_done(&g->y)) cco_yield();
}
cco_final:
- cco_end(true);
+ cco_end();
}
void Use(void)
@@ -48,9 +48,10 @@ void Use(void)
struct Generator g = {{&a}, {&b}};
- while (!interleaved(&g))
- printf("%d\n", g.value);
+ while (interleaved(&g), !cco_done(&g))
+ printf("%d ", g.value);
+ puts("");
c_drop(IVec, &a, &b);
}
diff --git a/misc/examples/coroutines.c b/misc/examples/coroutines.c
index bbe85874..00cedd84 100644
--- a/misc/examples/coroutines.c
+++ b/misc/examples/coroutines.c
@@ -4,16 +4,17 @@
// Demonstrate to call another coroutine from a coroutine:
// First create prime generator, then call fibonacci sequence:
+typedef long long llong;
bool is_prime(int64_t i) {
- for (int64_t j=2; j*j <= i; ++j)
+ for (llong j=2; j*j <= i; ++j)
if (i % j == 0) return false;
return true;
}
struct prime {
int count, idx;
- int64_t result, pos;
+ llong result, pos;
int cco_state;
};
@@ -44,7 +45,7 @@ bool prime(struct prime* g) {
struct fibonacci {
int count, idx;
- int64_t result, b;
+ llong result, b;
int cco_state;
};
@@ -59,7 +60,7 @@ bool fibonacci(struct fibonacci* g) {
if (g->count-- == 0)
cco_return;
if (++g->idx > 1) {
- int64_t sum = g->result + g->b; // NB! locals only lasts until next cco_yield!
+ llong sum = g->result + g->b; // NB! locals lasts only until next cco_yield/cco_await!
g->result = g->b;
g->b = sum;
}
@@ -81,13 +82,13 @@ struct combined {
bool combined(struct combined* C) {
cco_begin(C);
- cco_await(prime(&C->prm));
- cco_await(fibonacci(&C->fib));
+ cco_await_with(prime(&C->prm), false);
+ cco_await_with(fibonacci(&C->fib), false);
// Reuse the C->prm context and extend the count:
- C->prm.count = 8; C->prm.result += 2;
+ C->prm.count = 8, C->prm.result += 2;
cco_reset(&C->prm);
- cco_await(prime(&C->prm));
+ cco_await_with(prime(&C->prm), false);
cco_final: puts("final comb");
cco_end(true);
@@ -95,10 +96,11 @@ bool combined(struct combined* C) {
int main(void)
{
- struct combined comb = {.prm={.count=8}, .fib={14}};
+ struct combined c = {.prm={.count=8}, .fib={14}};
- while (!combined(&comb))
+ while (!combined(&c)) {
printf("Prime(%d)=%lld, Fib(%d)=%lld\n",
- comb.prm.idx, (long long)comb.prm.result,
- comb.fib.idx, (long long)comb.fib.result);
+ c.prm.idx, c.prm.result,
+ c.fib.idx, c.fib.result);
+ }
}