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