1 contributor
79 lines2.0 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>
6
7
enum {
8
Generator_Running,
9
Generator_Deleting,
10
Generator_Complete
11
};
12
13
struct Generator {
14
Coroutine *coroutine;
15
Coroutine *caller;
16
void *(*start)(void *);
17
void *param;
18
char state;
19
};
20
21
static void on_yield(void *this){
22
Generator *gen = (Generator *)this;
23
Coroutine_Continue(gen->caller, Coroutine_GetValue(gen->coroutine), true);
24
}
25
26
static void *do_start(void *this){
27
Generator *gen = (Generator *)this;
28
assert(gen->state == Generator_Running || gen->state == Generator_Deleting);
29
void *value;
30
if (gen->state == Generator_Running){
31
value = gen->start(gen->param);
32
} else {
33
// we are being deleted
34
value = NULL;
35
}
36
gen->state = Generator_Complete;
37
Coroutine_Continue(gen->caller, value, true);
38
return value;
39
}
40
41
Generator *Generator_New(void *(*start)(void *), void *param){
42
Generator *gen = malloc(sizeof(Generator));
43
gen->start = start;
44
gen->param = param;
45
gen->coroutine = Coroutine_New(gen, on_yield, do_start);
46
gen->state = Generator_Running;
47
return gen;
48
}
49
50
void Generator_Delete(Generator *gen){
51
assert(gen->state != Generator_Deleting);
52
if (gen->state == Generator_Running){
53
gen->state = Generator_Deleting;
54
gen->caller = Coroutine_GetActive();
55
Coroutine_Continue(gen->coroutine, gen, true);
56
Coroutine_Yield(NULL);
57
}
58
assert(gen->state == Generator_Complete);
59
Coroutine_Delete(gen->coroutine);
60
free(gen);
61
}
62
63
bool Generator_Next(Generator *gen, void **value){
64
assert(gen->state != Generator_Deleting);
65
if (gen->state == Generator_Complete){
66
return false;
67
}
68
gen->caller = Coroutine_GetActive();
69
Coroutine_Continue(gen->coroutine, gen, true);
70
*value = Coroutine_Yield(NULL);
71
return Coroutine_IsRunning(gen->coroutine);
72
}
73
74
bool Generator_Yield(void *value)
75
{
76
Generator *gen = Coroutine_Yield(value);
77
return gen->state == Generator_Running;
78
}
79