Hi all, after reading some post that reminds me of Duff device.
I wrote some helper function+macro to make coroutine in C by borrowing some ideas from Coroutines in C and rob pike Newsqueak
This is for sure not complete yet.
Still need improvement....
Feel free to give suggestion and idea/code/...
Code:
typedef struct {
int pc;
char stack[];
} context;
void new_context(context **c,void *local_context,size_t size)
{
if(*c) {
memcpy(local_context,(*c)->stack,size);
return ;
}
context *p;
p = malloc(sizeof *p + size);
memset(p,0,sizeof *p + size);
p->pc = 0;
memcpy(p->stack,local_context,size);
*c = p;
}
void c_return(context *c,void *local_c,size_t size)
{
memcpy(c->stack,local_c,size);
}
#define begin_context struct {
#define end_context } Context
#define coroutine_init(c) new_context(c,&Context,sizeof(Context) )
#define coroutine_start(c) switch((*c)->pc) { case 0:
#define coroutine_return(c,v) do { (*c)->pc=__LINE__; c_return(*c,&Context,sizeof(Context) ); return (v); case __LINE__:; } while(0)
#define coroutine_finish(c,v) } free(*c); *c = 0; return (v)
Usage:
Code:
int ascending(context **c)
{
begin_context
int i;
end_context;
coroutine_init(c);
coroutine_start(c);
for(Context.i = 0; ; Context.i++) {
coroutine_return(c,Context.i);
}
coroutine_finish(c,-1);
}
int series(context **c)
{
begin_context
context *as_c;
int n;
end_context;
coroutine_init(c);
coroutine_start(c);
Context.as_c = NULL;
while(1) {
int val = ascending(&Context.as_c);
Context.n = val * val;
coroutine_return(c,Context.n);
}
coroutine_finish(c,-1);
}
int sum_series(context **c)
{
begin_context
context *series_c;
int sum;
end_context;
coroutine_init(c);
coroutine_start(c);
Context.series_c = NULL;
Context.sum = 0;
while(1){
int val = series(&Context.series_c);
Context.sum += val;
coroutine_return(c,Context.sum);
}
coroutine_finish(c,-1);
}
int main(void)
{
context *c = 0;
context *c1 = 0;
context *c2 = 0;
int i;
printf("x \t x * x \t sig(xi) \n");
for(i=0;i<10;i++) {
printf("%d \t %d \t %d\n",ascending(&c1),series(&c),sum_series(&c2));
}
return 0;
}
Output:
Code:
x x * x sig(xi)
0 0 0
1 1 1
2 4 5
3 9 14
4 16 30
5 25 55
6 36 91
7 49 140
8 64 204
9 81 285