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