Skip to content

Instantly share code, notes, and snippets.

@lpereira

lpereira/co.c

Created Feb 26, 2019
Embed
What would you like to do?
#include <stdio.h>
#include <stdbool.h>
struct coro {
void *state;
};
struct range_coro {
struct coro base;
int cur, max, step;
};
#define co_init(s) \
if (!s->base.state) { \
s->base.state = &&coroutine_init_label; \
} else { \
goto *s->base.state; \
} \
coroutine_init_label: \
do { \
} while (0)
#define co_yield__impl(s, val, counter) \
do { \
typeof(val) __ret__ = (val); \
s->base.state = &&yield_point##counter; \
return __ret__; \
yield_point##counter:; \
} while (0)
#define co_yield_impl(s, val, counter) co_yield__impl(s, val, counter)
#define co_yield(s, val) co_yield_impl(s, val, __COUNTER__)
int range(struct range_coro *rc)
{
co_init(rc);
while (rc->cur <= rc->max) {
co_yield(rc, rc->cur);
rc->cur += rc->step;
}
while (true) {
co_yield(rc, -1);
}
}
struct inc_mul_coro {
struct coro base;
int cur;
};
int inc_mul(struct inc_mul_coro *imc, int v)
{
co_init(imc);
while (true) {
co_yield(imc, imc->cur * v);
imc->cur++;
}
}
struct inc_add_coro {
struct coro base;
int cur;
};
int inc_add(struct inc_add_coro *iac, int v)
{
co_init(iac);
while (true) {
co_yield(iac, iac->cur * v);
iac->cur++;
}
}
int main(int argc, char *argv[])
{
struct range_coro rc = { .cur = 0, .max = 100, .step = 7 };
struct inc_mul_coro imc = {};
struct inc_add_coro iac = {};
int v;
while ((v = range(&rc)) >= 0) {
printf("%d\n", inc_add(&iac, inc_mul(&imc, v)));
}
printf("calling again: %d\n", range(&rc));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment