8 months ago |
4 |
1 |
#include "generator.h" | ||
2 |
#include "coroutine.h" | ||||
3 |
#include <stdlib.h> | ||||
4 |
#include <stdio.h> | ||||
5 |
#include <assert.h> | ||||
7 months ago |
6 |
#include "cor_platform.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, | ||||
5 months ago |
50 |
size_t stack_size, | |||
8 months ago |
51 |
void *(*start)(void *), | |||
52 |
void *param | ||||
53 |
){ | ||||
8 months ago |
4 |
54 |
gen->start = start; | ||
55 |
gen->param = param; | ||||
5 months ago |
56 |
gen->coroutine = Coroutine_New(stack_size, do_start); | |||
8 months ago |
4 |
57 |
gen->state = Generator_Running; | ||
8 months ago |
58 |
} | |||
59 |
|||||
60 |
|||||
61 |
Generator *Generator_New( | ||||
5 months ago |
62 |
size_t stack_size, | |||
8 months ago |
63 |
void *(*start)(void *), | |||
64 |
void *param | ||||
65 |
){ | ||||
66 |
Generator *gen = malloc(sizeof(Generator)); | ||||
5 months ago |
67 |
Generator_ctor(gen, stack_size, start, param); | |||
8 months ago |
4 |
68 |
return gen; | ||
69 |
} | ||||
70 |
|||||
8 months ago |
71 |
||||
8 months ago |
72 |
void Generator_dtor( | |||
8 months ago |
73 |
Generator *gen | |||
74 |
){ | ||||
8 months ago |
4 |
75 |
assert(gen->state != Generator_Deleting); | ||
76 |
if (gen->state == Generator_Running){ | ||||
77 |
gen->state = Generator_Deleting; | ||||
78 |
gen->caller = Coroutine_GetActive(); | ||||
79 |
Coroutine_Continue(gen->coroutine, gen, true); | ||||
8 months ago |
80 |
Coroutine_Yield(NULL, on_yield_gen_caller, gen); | |||
8 months ago |
4 |
81 |
} | ||
82 |
assert(gen->state == Generator_Complete); | ||||
83 |
Coroutine_Delete(gen->coroutine); | ||||
8 months ago |
84 |
} | |||
85 |
|||||
86 |
void Generator_Delete( | ||||
87 |
Generator *gen | ||||
88 |
){ | ||||
89 |
Generator_dtor(gen); | ||||
8 months ago |
4 |
90 |
free(gen); | ||
91 |
} | ||||
92 |
|||||
8 months ago |
93 |
||||
94 |
bool Generator_Next( | ||||
95 |
Generator *gen, | ||||
96 |
void **value | ||||
97 |
){ | ||||
8 months ago |
4 |
98 |
assert(gen->state != Generator_Deleting); | ||
99 |
if (gen->state == Generator_Complete){ | ||||
100 |
return false; | ||||
101 |
} | ||||
102 |
gen->caller = Coroutine_GetActive(); | ||||
103 |
Coroutine_Continue(gen->coroutine, gen, true); | ||||
8 months ago |
104 |
*value = Coroutine_Yield(NULL, on_yield_gen_caller, gen); | |||
8 months ago |
4 |
105 |
return Coroutine_IsRunning(gen->coroutine); | ||
106 |
} | ||||
107 |
|||||
8 months ago |
108 |
||||
109 |
bool Generator_Yield( | ||||
110 |
void *value | ||||
111 |
) | ||||
8 months ago |
4 |
112 |
{ | ||
8 months ago |
113 |
assert(g_active_generator); | |||
114 |
Generator *gen = g_active_generator; | ||||
115 |
g_active_generator = NULL; | ||||
116 |
Coroutine_Yield(value, on_yield_gen, gen); | ||||
117 |
g_active_generator = gen; | ||||
8 months ago |
4 |
118 |
return gen->state == Generator_Running; | ||
119 |
} | ||||
120 |