summaryrefslogtreecommitdiffhomepage
path: root/include/stc/algo/coroutine.h
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-05-02 07:20:29 +0200
committerTyge Løvset <[email protected]>2023-05-02 07:20:29 +0200
commit2adea8b3b06ebe1b2152870862100f7e7985cfdf (patch)
tree7d37dc14784f33e9b40888253aa5c7183d81c6b0 /include/stc/algo/coroutine.h
parent399eb8d0e1de2839d826a9e0cf123d90d00b0018 (diff)
downloadSTC-modified-2adea8b3b06ebe1b2152870862100f7e7985cfdf.tar.gz
STC-modified-2adea8b3b06ebe1b2152870862100f7e7985cfdf.zip
Improved coroutine.h, added new coro examples.
Diffstat (limited to 'include/stc/algo/coroutine.h')
-rw-r--r--include/stc/algo/coroutine.h49
1 files changed, 39 insertions, 10 deletions
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index 6c1d7d28..4b7bee5f 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -26,38 +26,38 @@
#include <stdio.h>
#include <stc/algo/coroutine.h>
-struct iterate {
+struct coroutine {
int max_x, max_y;
int x, y;
int cco_state; // required member
};
-bool iterate(struct iterate* I) {
+bool coroutine(struct coroutine* 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_yield(false);
cco_final:
- puts("final");
- cco_end(false);
+ puts("final");
+ cco_end(true);
}
int main(void) {
- struct iterate it = {.max_x=3, .max_y=3};
+ struct coroutine it = {.max_x=3, .max_y=3};
int n = 0;
- while (iterate(&it))
+ while (!coroutine(&it))
{
printf("%d %d\n", it.x, it.y);
// example of early stop:
- if (++n == 20) cco_stop(&it); // signal to stop at next
+ if (++n == 7) cco_stop(&it); // signal to stop at next
}
return 0;
}
*/
#include <stc/ccommon.h>
-enum {
+enum cco_states {
cco_state_final = -1,
cco_state_done = -2,
};
@@ -89,7 +89,7 @@ enum {
case __LINE__: if (cond) return retval; \
} while (0)
-#define cco_await(cond) cco_await_while(!(cond), true)
+#define cco_await(promise) cco_await_while(!(promise), false)
#define cco_final \
case cco_state_final: \
@@ -110,4 +110,33 @@ enum {
if (*_state == cco_state_done) *_state = 0; \
} while (0)
+
+typedef struct {
+ int count;
+} cco_semaphore;
+
+/**
+ * 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
+ * protothread will continue.
+ */
+#define cco_await_sem(sem) \
+ do { \
+ cco_await((sem)->count > 0); \
+ --(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
+ * eventually will cause waiting "threads" to continue executing.
+ */
+#define cco_signal_sem(sem) ++(sem)->count
+#define cco_reset_sem(sem, value) ((sem)->count = value)
+
#endif