9 months ago |
4 |
1 |
#include "generator.h" | ||
2 |
#include "coroutine.h" | ||||
3 |
#include <stdlib.h> | ||||
4 |
#include <stdio.h> | ||||
5 |
#include <assert.h> | ||||
9 months ago |
6 |
#include "cor_thread_local.h" | |||
9 months ago |
4 |
7 |
|||
8 |
enum { | ||||
9 |
Generator_Running, | ||||
10 |
Generator_Deleting, | ||||
11 |
Generator_Complete | ||||
12 |
}; | ||||
13 |
|||||
14 |
struct Generator { | ||||
15 |
Coroutine *coroutine; | ||||
16 |
Coroutine *caller; | ||||
17 |
void *(*start)(void *); | ||||
18 |
void *param; | ||||
19 |
char state; | ||||
20 |
}; | ||||
21 |
|||||
9 months ago |
22 |
||||
9 months ago |
23 |
_Cor_thread_local Generator *g_active_generator = NULL; | |||
24 |
|||||
9 months ago |
25 |
||||
26 |
static void on_yield_gen( | ||||
27 |
void *this | ||||
28 |
){ | ||||
9 months ago |
4 |
29 |
Generator *gen = (Generator *)this; | ||
30 |
Coroutine_Continue(gen->caller, Coroutine_GetValue(gen->coroutine), true); | ||||
31 |
} | ||||
32 |
|||||
9 months ago |
33 |
||||
34 |
static void on_yield_gen_caller( | ||||
35 |
void *this | ||||
36 |
){ | ||||
9 months ago |
37 |
(void)this; | |||
38 |
} | ||||
39 |
|||||
9 months ago |
40 |
||||
41 |
static void *do_start( | ||||
42 |
void *this | ||||
43 |
){ | ||||
9 months ago |
4 |
44 |
Generator *gen = (Generator *)this; | ||
9 months ago |
45 |
g_active_generator = this; | |||
9 months ago |
4 |
46 |
assert(gen->state == Generator_Running || gen->state == Generator_Deleting); | ||
47 |
void *value; | ||||
48 |
if (gen->state == Generator_Running){ | ||||
9 months ago |
49 |
g_active_generator = gen; | |||
9 months ago |
4 |
50 |
value = gen->start(gen->param); | ||
9 months ago |
51 |
g_active_generator = NULL; | |||
9 months ago |
4 |
52 |
} else { | ||
53 |
// we are being deleted | ||||
54 |
value = NULL; | ||||
55 |
} | ||||
56 |
gen->state = Generator_Complete; | ||||
57 |
Coroutine_Continue(gen->caller, value, true); | ||||
58 |
return value; | ||||
59 |
} | ||||
60 |
|||||
9 months ago |
61 |
||||
62 |
Generator *Generator_New( | ||||
63 |
void *(*start)(void *), | ||||
64 |
void *param | ||||
65 |
){ | ||||
9 months ago |
4 |
66 |
Generator *gen = malloc(sizeof(Generator)); | ||
67 |
gen->start = start; | ||||
68 |
gen->param = param; | ||||
9 months ago |
69 |
gen->coroutine = Coroutine_New(do_start); | |||
9 months ago |
4 |
70 |
gen->state = Generator_Running; | ||
71 |
return gen; | ||||
72 |
} | ||||
73 |
|||||
9 months ago |
74 |
||||
75 |
void Generator_Delete( | ||||
76 |
Generator *gen | ||||
77 |
){ | ||||
9 months ago |
4 |
78 |
assert(gen->state != Generator_Deleting); | ||
79 |
if (gen->state == Generator_Running){ | ||||
80 |
gen->state = Generator_Deleting; | ||||
81 |
gen->caller = Coroutine_GetActive(); | ||||
82 |
Coroutine_Continue(gen->coroutine, gen, true); | ||||
9 months ago |
83 |
Coroutine_Yield(NULL, on_yield_gen_caller, gen); | |||
9 months ago |
4 |
84 |
} | ||
85 |
assert(gen->state == Generator_Complete); | ||||
86 |
Coroutine_Delete(gen->coroutine); | ||||
87 |
free(gen); | ||||
88 |
} | ||||
89 |
|||||
9 months ago |
90 |
||||
91 |
bool Generator_Next( | ||||
92 |
Generator *gen, | ||||
93 |
void **value | ||||
94 |
){ | ||||
9 months ago |
4 |
95 |
assert(gen->state != Generator_Deleting); | ||
96 |
if (gen->state == Generator_Complete){ | ||||
97 |
return false; | ||||
98 |
} | ||||
99 |
gen->caller = Coroutine_GetActive(); | ||||
100 |
Coroutine_Continue(gen->coroutine, gen, true); | ||||
9 months ago |
101 |
*value = Coroutine_Yield(NULL, on_yield_gen_caller, gen); | |||
9 months ago |
4 |
102 |
return Coroutine_IsRunning(gen->coroutine); | ||
103 |
} | ||||
104 |
|||||
9 months ago |
105 |
||||
106 |
bool Generator_Yield( | ||||
107 |
void *value | ||||
108 |
) | ||||
9 months ago |
4 |
109 |
{ | ||
9 months ago |
110 |
assert(g_active_generator); | |||
111 |
Generator *gen = g_active_generator; | ||||
112 |
g_active_generator = NULL; | ||||
113 |
Coroutine_Yield(value, on_yield_gen, gen); | ||||
114 |
g_active_generator = gen; | ||||
9 months ago |
4 |
115 |
return gen->state == Generator_Running; | ||
116 |
} | ||||
117 |