1 contributor
79 lines2.0 KB
1#include "generator.h"
2#include "coroutine.h"
3#include <stdlib.h>
4#include <stdio.h>
5#include <assert.h>
6
7enum {
8 Generator_Running,
9 Generator_Deleting,
10 Generator_Complete
11};
12
13struct Generator {
14 Coroutine *coroutine;
15 Coroutine *caller;
16 void *(*start)(void *);
17 void *param;
18 char state;
19};
20
21static void on_yield(void *this){
22 Generator *gen = (Generator *)this;
23 Coroutine_Continue(gen->caller, Coroutine_GetValue(gen->coroutine), true);
24}
25
26static void *do_start(void *this){
27 Generator *gen = (Generator *)this;
28 assert(gen->state == Generator_Running || gen->state == Generator_Deleting);
29 void *value;
30 if (gen->state == Generator_Running){
31 value = gen->start(gen->param);
32 } else {
33 // we are being deleted
34 value = NULL;
35 }
36 gen->state = Generator_Complete;
37 Coroutine_Continue(gen->caller, value, true);
38 return value;
39}
40
41Generator *Generator_New(void *(*start)(void *), void *param){
42 Generator *gen = malloc(sizeof(Generator));
43 gen->start = start;
44 gen->param = param;
45 gen->coroutine = Coroutine_New(gen, on_yield, do_start);
46 gen->state = Generator_Running;
47 return gen;
48}
49
50void Generator_Delete(Generator *gen){
51 assert(gen->state != Generator_Deleting);
52 if (gen->state == Generator_Running){
53 gen->state = Generator_Deleting;
54 gen->caller = Coroutine_GetActive();
55 Coroutine_Continue(gen->coroutine, gen, true);
56 Coroutine_Yield(NULL);
57 }
58 assert(gen->state == Generator_Complete);
59 Coroutine_Delete(gen->coroutine);
60 free(gen);
61}
62
63bool Generator_Next(Generator *gen, void **value){
64 assert(gen->state != Generator_Deleting);
65 if (gen->state == Generator_Complete){
66 return false;
67 }
68 gen->caller = Coroutine_GetActive();
69 Coroutine_Continue(gen->coroutine, gen, true);
70 *value = Coroutine_Yield(NULL);
71 return Coroutine_IsRunning(gen->coroutine);
72}
73
74bool Generator_Yield(void *value)
75{
76 Generator *gen = Coroutine_Yield(value);
77 return gen->state == Generator_Running;
78}
79