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