86 91
93
Generator works with chaining - adjust chaining demo to actually chain (using generators)
on 8:43 AM Jun 9 2026
92
93
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "generator.h"
#include "coroutine.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "cor_platform.h"
_Cor_thread_local Generator *g_active_generator = NULL;
static void
on_yield_gen(
void *this
){
Generator *gen = (Generator *)this;
Coroutine_NS(Continue)(gen->caller, Coroutine_NS(GetValue)(gen->coroutine), true);
}
static void
on_yield_gen_caller(
void *this
){
(void)this;
}
static void *
do_start(
void *this
){
Generator *gen = (Generator *)this;
g_active_generator = this;
assert(gen->state == Generator_Running || gen->state == Generator_Deleting);
void *value;
if (gen->state == Generator_Running){
g_active_generator = gen;
value = gen->start(gen->param);
g_active_generator = NULL;
} else {
// we are being deleted
value = NULL;
}
gen->state = Generator_Complete;
Coroutine_NS(Continue)(gen->caller, value, true);
return value;
}
void
Generator_ctor(
Generator *gen,
size_t min_stack,
size_t min_stack_headroom,
void *(*start)(void *),
void *param
){
gen->start = start;
gen->param = param;
gen->coroutine = Coroutine_NS(New)(min_stack, min_stack_headroom, do_start);
gen->state = Generator_Running;
}
Generator *
Generator_New(
size_t min_stack,
size_t min_stack_headroom,
void *(*start)(void *),
void *param
){
Generator *gen = malloc(sizeof(Generator));
Generator_ctor(gen, min_stack, min_stack_headroom, start, param);
return gen;
}
void
Generator_dtor(
Generator *gen
){
assert(gen->state != Generator_Deleting);
if (gen->state == Generator_Running){
gen->state = Generator_Deleting;
gen->caller = Coroutine_NS(GetActive)();
Coroutine_NS(Continue)(gen->coroutine, gen, true);
Coroutine_NS(Yield)(NULL, on_yield_gen_caller, gen);
}
assert(gen->state == Generator_Complete);
Coroutine_NS(Delete)(gen->coroutine);
}
void
Generator_Delete(
Generator *gen
){
Generator_dtor(gen);
free(gen);
}
bool
Generator_Next(
Generator *gen,
void **value
){
assert(gen->state != Generator_Deleting);
if (gen->state == Generator_Complete){
return false;
}
gen->caller = Coroutine_NS(GetActive)();
Coroutine_NS(Continue)(gen->coroutine, gen, true);
*value = Coroutine_NS(Yield)(NULL, on_yield_gen_caller, gen);
return Coroutine_NS(IsRunning)(gen->coroutine);
}
bool
Generator_Yield(
void *value
)
{
assert(g_active_generator);
Generator *gen = g_active_generator;
g_active_generator = NULL;
Coroutine_NS(Yield)(value, on_yield_gen, gen);
g_active_generator = gen;
return gen->state == Generator_Running;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "generator.h"
#include "coroutine.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "cor_platform.h"
_Cor_thread_local Generator *g_active_generator = NULL;
static void
on_yield_gen(
void *this
){
(void)this;
}
static void
on_yield_gen_caller(
void *this
){
(void)this;
}
static void *
do_start(
void *this
){
Generator *gen = (Generator *)this;
g_active_generator = this;
assert(gen->state == Generator_Running || gen->state == Generator_Deleting);
void *value;
if (gen->state == Generator_Running){
g_active_generator = gen;
value = gen->start(gen->param);
g_active_generator = NULL;
} else {
// we are being deleted
value = NULL;
}
gen->state = Generator_Complete;
Coroutine_NS(Continue)(gen->caller, value, true);
return value;
}
void
Generator_ctor(
Generator *gen,
size_t min_stack,
size_t min_stack_headroom,
void *(*start)(void *),
void *param
){
gen->start = start;
gen->param = param;
gen->coroutine = Coroutine_NS(New)(min_stack, min_stack_headroom, do_start);
gen->yielded_coroutine = gen->coroutine;
gen->state = Generator_Running;
}
Generator *
Generator_New(
size_t min_stack,
size_t min_stack_headroom,
void *(*start)(void *),
void *param
){
Generator *gen = malloc(sizeof(Generator));
Generator_ctor(gen, min_stack, min_stack_headroom, start, param);
return gen;
}
void
Generator_dtor(
Generator *gen
){
assert(gen->state != Generator_Deleting);
if (gen->state == Generator_Running){
gen->state = Generator_Deleting;
gen->caller = Coroutine_NS(GetActive)();
Coroutine_NS(Continue)(gen->yielded_coroutine, gen, true);
Coroutine_NS(Yield)(NULL, on_yield_gen_caller, gen);
}
assert(gen->state == Generator_Complete);
Coroutine_NS(Delete)(gen->coroutine);
}
void
Generator_Delete(
Generator *gen
){
Generator_dtor(gen);
free(gen);
}
bool
Generator_Next(
Generator *gen,
void **value
){
assert(gen->state != Generator_Deleting);
if (gen->state == Generator_Complete){
return false;
}
gen->caller = Coroutine_NS(GetActive)();
Coroutine_NS(Continue)(gen->yielded_coroutine, gen, true);
*value = Coroutine_NS(Yield)(NULL, on_yield_gen_caller, gen);
return Coroutine_NS(IsRunning)(gen->coroutine);
}
bool
Generator_Yield(
void *value
)
{
assert(g_active_generator);
Generator *gen = g_active_generator;
g_active_generator = NULL;
gen->yielded_coroutine = Coroutine_NS(GetActive)();
Coroutine_NS(Continue)(gen->caller, value, true);
Coroutine_NS(Yield)(value, on_yield_gen, NULL);
g_active_generator = gen;
return gen->state == Generator_Running;
}