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" | |||
9 months ago |
4 |
7 |
|||
8 |
|||||
9 months ago |
9 |
_Cor_thread_local Generator *g_active_generator = NULL; | |||
10 |
|||||
9 months ago |
11 |
||||
Last week |
12 |
static void | |||
13 |
on_yield_gen( | ||||
9 months ago |
14 |
void *this | |||
15 |
){ | ||||
9 months ago |
4 |
16 |
Generator *gen = (Generator *)this; | ||
Last month |
17 |
Coroutine_NS(Continue)(gen->caller, Coroutine_NS(GetValue)(gen->coroutine), true); | |||
9 months ago |
4 |
18 |
} | ||
19 |
|||||
9 months ago |
20 |
||||
Last week |
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 |
||||
Last week |
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; | ||||
Last month |
46 |
Coroutine_NS(Continue)(gen->caller, value, true); | |||
9 months ago |
4 |
47 |
return value; | ||
48 |
} | ||||
49 |
|||||
9 months ago |
50 |
||||
Last week |
51 |
void | |||
52 |
Generator_ctor( | ||||
9 months ago |
53 |
Generator *gen, | |||
Last week |
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; | ||||
Last week |
61 |
gen->coroutine = Coroutine_NS(New)(min_stack, min_stack_headroom, do_start); | |||
9 months ago |
4 |
62 |
gen->state = Generator_Running; | ||
9 months ago |
63 |
} | |||
64 |
|||||
65 |
|||||
Last week |
66 |
Generator * | |||
67 |
Generator_New( | ||||
68 |
size_t min_stack, | ||||
69 |
size_t min_stack_headroom, | ||||
9 months ago |
70 |
void *(*start)(void *), | |||
71 |
void *param | ||||
72 |
){ | ||||
73 |
Generator *gen = malloc(sizeof(Generator)); | ||||
Last week |
74 |
Generator_ctor(gen, min_stack, min_stack_headroom, start, param); | |||
9 months ago |
4 |
75 |
return gen; | ||
76 |
} | ||||
77 |
|||||
9 months ago |
78 |
||||
Last week |
79 |
void | |||
80 |
Generator_dtor( | ||||
9 months ago |
81 |
Generator *gen | |||
82 |
){ | ||||
9 months ago |
4 |
83 |
assert(gen->state != Generator_Deleting); | ||
84 |
if (gen->state == Generator_Running){ | ||||
85 |
gen->state = Generator_Deleting; | ||||
Last month |
86 |
gen->caller = Coroutine_NS(GetActive)(); | |||
87 |
Coroutine_NS(Continue)(gen->coroutine, gen, true); | ||||
88 |
Coroutine_NS(Yield)(NULL, on_yield_gen_caller, gen); | ||||
9 months ago |
4 |
89 |
} | ||
90 |
assert(gen->state == Generator_Complete); | ||||
Last month |
91 |
Coroutine_NS(Delete)(gen->coroutine); | |||
9 months ago |
92 |
} | |||
93 |
|||||
Last week |
94 |
void | |||
95 |
Generator_Delete( | ||||
9 months ago |
96 |
Generator *gen | |||
97 |
){ | ||||
98 |
Generator_dtor(gen); | ||||
9 months ago |
4 |
99 |
free(gen); | ||
100 |
} | ||||
101 |
|||||
9 months ago |
102 |
||||
Last week |
103 |
bool | |||
104 |
Generator_Next( | ||||
9 months ago |
105 |
Generator *gen, | |||
106 |
void **value | ||||
107 |
){ | ||||
9 months ago |
4 |
108 |
assert(gen->state != Generator_Deleting); | ||
109 |
if (gen->state == Generator_Complete){ | ||||
110 |
return false; | ||||
111 |
} | ||||
Last month |
112 |
gen->caller = Coroutine_NS(GetActive)(); | |||
113 |
Coroutine_NS(Continue)(gen->coroutine, gen, true); | ||||
114 |
*value = Coroutine_NS(Yield)(NULL, on_yield_gen_caller, gen); | ||||
115 |
return Coroutine_NS(IsRunning)(gen->coroutine); | ||||
9 months ago |
4 |
116 |
} | ||
117 |
|||||
9 months ago |
118 |
||||
Last week |
119 |
bool | |||
120 |
Generator_Yield( | ||||
9 months ago |
121 |
void *value | |||
122 |
) | ||||
9 months ago |
4 |
123 |
{ | ||
9 months ago |
124 |
assert(g_active_generator); | |||
125 |
Generator *gen = g_active_generator; | ||||
126 |
g_active_generator = NULL; | ||||
Last month |
127 |
Coroutine_NS(Yield)(value, on_yield_gen, gen); | |||
9 months ago |
128 |
g_active_generator = gen; | |||
9 months ago |
4 |
129 |
return gen->state == Generator_Running; | ||
130 |
} | ||||
131 |