A generator library in C
Wikipedia explains the concept of generator
. The main use cases are
- Seperate
producer
andconsumer
- Avoid
callback
functions.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "cg.h"
uintptr_t fib(uintptr_t limit, uintptr_t undef)
{
uintptr_t a=1;
uintptr_t b=1;
uintptr_t t= a + b;
uintptr_t count = 0;
for(t = a+b; t < limit; t = a+b){
count = cg_yield(__builtin_frame_address(0), t);
a = b; b = t;
fprintf(stderr,__FILE__ ":%d:[%s] %ld => %ld\n", __LINE__, __FUNCTION__
,count, t);
}
return undef;
}
int main(int argc, char *argv[])
{
const uintptr_t undef = 1976;
cg_t co; cg_init(&co,(void*)fib,100,undef);
uintptr_t x = 0;
uintptr_t count = 0;
for(x = cg_invoke(&co, count++);
x != undef;
x = cg_invoke(&co, count++)){
fprintf(stderr,__FILE__ ":%d:[%s] %ld \n",__LINE__, __FUNCTION__,x);
}
assert(cg_is_done(&co));
return 0;
}
cg_init
at line 22, initialize a new generator.- function
cg_fib
is not started. cg_lib
will start with two arguments,limit
andundef
.limit
andundef
could be any user defined value.
- function
cg_invoke
at line 25 and 27, starts the generator.- the first argument
co
is the generator. - the second argument
count
is the return value ofcg_yield
, initially, it doesn't make sense. - At first time,
fib
starts from the beginning, i.e. line 7.
- the first argument
cg_yield
at line 12,cg_fib
suspended and control return tomain
- the first argument must be
__builtin_frame_address(0)
- the second argument is the
yield
value,t
. cg_invoke
returns the yield valuet
.- the stack and enviroment of
cg_fib
is saved and could be restarted later.
- the first argument must be
- return of
cg_lib
at line 17.- the return value of
cg_lib
is also the return value ofcg_invoke
. - after that,
cg_is_done(co)
will return1
, otherwise,0
.
- the return value of
see https://github.com/wcy123/cg/blob/master/implementation.md for the detail document of the implemention.