1 contributor
93 lines2.4 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
_Cor_thread_local Generator *g_active_generator = NULL;
23
24
static void on_yield_gen(void *this){
9 months ago
4
25
Generator *gen = (Generator *)this;
26
Coroutine_Continue(gen->caller, Coroutine_GetValue(gen->coroutine), true);
27
}
28
9 months ago
29
static void on_yield_gen_caller(void *this){
30
(void)this;
31
}
32
9 months ago
4
33
static void *do_start(void *this){
34
Generator *gen = (Generator *)this;
9 months ago
35
g_active_generator = this;
9 months ago
4
36
assert(gen->state == Generator_Running || gen->state == Generator_Deleting);
37
void *value;
38
if (gen->state == Generator_Running){
9 months ago
39
g_active_generator = gen;
9 months ago
4
40
value = gen->start(gen->param);
9 months ago
41
g_active_generator = NULL;
9 months ago
4
42
} else {
43
// we are being deleted
44
value = NULL;
45
}
46
gen->state = Generator_Complete;
47
Coroutine_Continue(gen->caller, value, true);
48
return value;
49
}
50
51
Generator *Generator_New(void *(*start)(void *), void *param){
52
Generator *gen = malloc(sizeof(Generator));
53
gen->start = start;
54
gen->param = param;
9 months ago
55
gen->coroutine = Coroutine_New(do_start);
9 months ago
4
56
gen->state = Generator_Running;
57
return gen;
58
}
59
60
void Generator_Delete(Generator *gen){
61
assert(gen->state != Generator_Deleting);
62
if (gen->state == Generator_Running){
63
gen->state = Generator_Deleting;
64
gen->caller = Coroutine_GetActive();
65
Coroutine_Continue(gen->coroutine, gen, true);
9 months ago
66
Coroutine_Yield(NULL, on_yield_gen_caller, gen);
9 months ago
4
67
}
68
assert(gen->state == Generator_Complete);
69
Coroutine_Delete(gen->coroutine);
70
free(gen);
71
}
72
73
bool Generator_Next(Generator *gen, void **value){
74
assert(gen->state != Generator_Deleting);
75
if (gen->state == Generator_Complete){
76
return false;
77
}
78
gen->caller = Coroutine_GetActive();
79
Coroutine_Continue(gen->coroutine, gen, true);
9 months ago
80
*value = Coroutine_Yield(NULL, on_yield_gen_caller, gen);
9 months ago
4
81
return Coroutine_IsRunning(gen->coroutine);
82
}
83
84
bool Generator_Yield(void *value)
85
{
9 months ago
86
assert(g_active_generator);
87
Generator *gen = g_active_generator;
88
g_active_generator = NULL;
89
Coroutine_Yield(value, on_yield_gen, gen);
90
g_active_generator = gen;
9 months ago
4
91
return gen->state == Generator_Running;
92
}
93