A generator library in C
Wikipedia explains the concept of generator. The main use cases are
- Seperate
producerandconsumer - Avoid
callbackfunctions.
#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_initat line 22, initialize a new generator.- function
cg_fibis not started. cg_libwill start with two arguments,limitandundef.limitandundefcould be any user defined value.
- function
cg_invokeat line 25 and 27, starts the generator.- the first argument
cois the generator. - the second argument
countis the return value ofcg_yield, initially, it doesn't make sense. - At first time,
fibstarts from the beginning, i.e. line 7.
- the first argument
cg_yieldat line 12,cg_fibsuspended and control return tomain- the first argument must be
__builtin_frame_address(0) - the second argument is the
yieldvalue,t. cg_invokereturns the yield valuet.- the stack and enviroment of
cg_fibis saved and could be restarted later.
- the first argument must be
- return of
cg_libat line 17.- the return value of
cg_libis 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.