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