1 contributor
117 lines2.5 KB
Newer
Older
-
+
commited
{line.log.rev}
on
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