01 #define GENF_ALLOW_NEXT 1
02 #define GENF_DONE 2 //When the generator has exited
03 #define GENF_DATA_READY 4
04 class CGenerator {
05   U8 (*fptr)(I64);
06   CTask *task;
07   I64 is_done,flags;
08   I64 ret_data;
09   I64 input_data;
10   I64 user_data,user_data2;
11   F64 timeout_tS;
12   I64 maximum,generated;
13 };
14 U0 GeneratorKill(CGenerator *gen) {
15   Kill(gen->task,FALSE);
16 }
17 U0 GeneratorYield(I64 value) {
18   CGenerator *gen=Fs->user_data;
19   gen->ret_data=value;
20   gen->generated++;
21   if(gen->timeout_tS&&gen->timeout_tS<tS) {
22     GeneratorKill(gen);
23   }
24   if(gen->generated>gen->maximum) {
25     GeneratorKill(gen);
26   }
27   LBts(&gen->flags,GENF_DATA_READY);
28   while(!LBtr(&gen->flags,GENF_ALLOW_NEXT)) {
29     Fs->wake_jiffy=I64_MAX;
30     Yield;
31   }
32 }
33 CGenerator *GeneratorSelf(CTask *t=NULL) {
34   return FramePtr("#Generator",t);
35 }
36 U0 GeneratorExit() {
37   CGenerator *gen=Fs->user_data;
38   LBts(&gen->flags,GENF_DONE);
39   Exit;
40 }
41 U0 GeneratorTask(CGenerator *gen) {
42   Fs->task_end_cb=&GeneratorExit;
43   Fs->user_data=gen;
44   FramePtrAdd("#Generator",gen); 
45   if(gen->fptr)
46       (gen->fptr)(gen->input_data);
47   LBts(&gen->flags,GENF_DONE);
48 }
49 CGenerator *GeneratorNew(U8 (*fptr)(I64),I64 data) {
50   static I64 c=0;
51 //  c=(c+1)%mp_cnt;
52   CGenerator *gen=CAlloc(sizeof CGenerator);
53   gen->fptr=fptr;
54   gen->input_data=data;
55   gen->maximum=0x10000;
56   gen->task=Spawn(&GeneratorTask,gen,"Generator",c,Fs);
57   return gen;
58 }
59 Bool GeneratorGet(CGenerator *gen,I64 *res) {
60   while(TRUE)  {
61     Yield;
62     if(LBtr(&gen->flags,GENF_DATA_READY)) {
63       LBts(&gen->flags,GENF_ALLOW_NEXT);
64       if(res) *res=gen->ret_data;
65       return TRUE;
66     }
67     if(Bt(&gen->flags,GENF_DONE)) {
68       Free(gen);
69       return FALSE;
70     }
71     gen->task->wake_jiffy=0;
72   }  
73 }
74 #if 0
75 I64 Count(I64 to) {
76   I64 i=0;
77   for(i=0;i!=to;i++)
78     GeneratorYield(i);
79 }
80 CGenerator *gen=GeneratorNew(&Count,10);
81 I64 value;
82 while(GeneratorGet(gen,&value)) {
83   "I got %d\n",value;
84   Sleep(1000);
85 }
86 #endif