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