]> git.ozlabs.org Git - ccan/blob - ccan/generator/generator.h
tal: allow notifiers on NULL.
[ccan] / ccan / generator / generator.h
1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
2 #ifndef CCAN_GENERATOR_H
3 #define CCAN_GENERATOR_H
4 #include "config.h"
5
6 #if !HAVE_TYPEOF
7 #error Generators require typeof
8 #endif
9
10 #if !HAVE_STATEMENT_EXPR
11 #error Generators require statement expressions
12 #endif
13
14 #include <assert.h>
15 #include <stddef.h>
16 #include <stdbool.h>
17
18 #include <ccan/cppmagic/cppmagic.h>
19 #include <ccan/compiler/compiler.h>
20 #include <ccan/coroutine/coroutine.h>
21
22 #if !COROUTINE_AVAILABLE
23 #error Generators require coroutines
24 #endif
25
26 /*
27  * Internals - included just for the use of inlines and macros
28  */
29
30 struct generator_ {
31         struct coroutine_state gen;
32         struct coroutine_state caller;
33         bool complete;
34         void *base;
35 };
36
37 static inline struct generator_ *generator_state_(const void *ret)
38 {
39         return (struct generator_ *)ret - 1;
40 }
41
42 static inline void *generator_argp_(const void *ret)
43 {
44         return generator_state_(ret)->base;
45 }
46
47 struct generator_incomplete_;
48
49 #define generator_rtype_(gen_)                  \
50         typeof((*(gen_))((struct generator_incomplete_ *)NULL))
51
52 void *generator_new_(void (*fn)(void *), size_t retsize);
53 void generator_free_(void *ret, size_t retsize);
54
55 /*
56  * API
57  */
58
59 /**
60  * generator_t - type for an in-progress generator
61  * @rtype: type of values the generator yield
62  */
63 #define generator_t(rtype_)                     \
64         typeof(rtype_ (*)(struct generator_incomplete_ *))
65
66 /**
67  * generator_declare - declare (but don't define) a generator function
68  * @name: name for the generator
69  * @rtype: return type for the generator
70  *
71  * Declares (as an extern) a generator function named @name, which
72  * will yield return values of type @rtype.
73  *
74  * Example:
75  *      generator_declare(count_to_3, int);
76  */
77 #define generator_declare(name_, rtype_, ...)   \
78         generator_t(rtype_) name_(generator_parms_outer_(__VA_ARGS__))
79
80 /**
81  * generator_def - define a generator function
82  * @name: name for the generator
83  * @rtype: return type for the generator
84  *
85  * Define a generator function named @name yielding return values of
86  * type @rtype.  The generator_def() line is followed immediately by a
87  * block containing the generator's code.
88  *
89  * Example:
90  *      generator_def(count_to_3, int)
91  *      {
92  *              generator_yield(1);
93  *              generator_yield(2);
94  *              generator_yield(3);
95  *      }
96  */
97 #define generator_parm_(t_, n_)                 t_ n_
98 #define generator_parms_(...)                                           \
99         CPPMAGIC_2MAP(generator_parm_, __VA_ARGS__)
100 #define generator_parms_inner_(...)                                     \
101         CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__))                 \
102                 (, generator_parms_(__VA_ARGS__))()
103 #define generator_parms_outer_(...)                                     \
104         CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
105                 (generator_parms_(__VA_ARGS__))(void)
106 #define generator_argfield_(t_, n_)             t_ n_;
107 #define generator_argstruct_(...)                                       \
108         struct {                                                        \
109                 CPPMAGIC_JOIN(, CPPMAGIC_2MAP(generator_argfield_,      \
110                                               __VA_ARGS__))             \
111         }
112 #define generator_arg_unpack_(t_, n_)           args->n_
113 #define generator_args_unpack_(...)             \
114         CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__))                 \
115                 (, CPPMAGIC_2MAP(generator_arg_unpack_, __VA_ARGS__))()
116 #define generator_arg_pack_(t_, n_)             args->n_ = n_
117 #define generator_args_pack_(...)                                       \
118         CPPMAGIC_JOIN(;, CPPMAGIC_2MAP(generator_arg_pack_, __VA_ARGS__))
119 #define generator_def_(name_, rtype_, storage_, ...)                    \
120         static void name_##_generator_(rtype_ *ret_                     \
121                                        generator_parms_inner_(__VA_ARGS__)); \
122         static void name_##_generator__(void *ret)                      \
123         {                                                               \
124                 struct generator_ *gen;                                 \
125                 UNNEEDED generator_argstruct_(__VA_ARGS__) *args;       \
126                 gen = generator_state_(ret);                            \
127                 args = generator_argp_(ret);                            \
128                 name_##_generator_(ret generator_args_unpack_(__VA_ARGS__)); \
129                 gen->complete = true;                                   \
130                 coroutine_jump(&gen->caller);                           \
131                 assert(0);                                              \
132         }                                                               \
133         storage_ generator_t(rtype_)                                    \
134         name_(generator_parms_outer_(__VA_ARGS__))                      \
135         {                                                               \
136                 generator_t(rtype_) gen = generator_new_(name_##_generator__, \
137                                                          sizeof(rtype_)); \
138                 UNNEEDED generator_argstruct_(__VA_ARGS__) *args =      \
139                         generator_argp_(gen);                           \
140                 generator_args_pack_(__VA_ARGS__);                      \
141                 return gen;                                             \
142         }                                                               \
143         static void name_##_generator_(rtype_ *ret_                     \
144                                        generator_parms_inner_(__VA_ARGS__))
145 #define generator_def(name_, rtype_, ...)       \
146         generator_def_(name_, rtype_, , __VA_ARGS__)
147
148 /**
149  * generator_def_static - define a private / local generator function
150  * @name: name for the generator
151  * @rtype: return type for the generator
152  *
153  * As generator_def, but the resulting generator function will be
154  * local to this module.
155  */
156 #define generator_def_static(name_, rtype_, ...)        \
157         generator_def_(name_, rtype_, static, __VA_ARGS__)
158
159 /**
160  * generator_yield - yield (return) a value from a generator
161  * @val: value to yield
162  *
163  * Invoke only from within a generator.  Yield the given value to the
164  * caller.  This will stop execution of the generator code until the
165  * caller next invokes generator_next(), at which point it will
166  * continue from the generator_yield statement.
167  */
168 #define generator_yield(val_)                                           \
169         do {                                                            \
170                 struct generator_ *gen_ = generator_state_(ret_);       \
171                 *(ret_) = (val_);                                       \
172                 coroutine_switch(&gen_->gen, &gen_->caller);            \
173         } while (0)
174
175 /**
176  * generator_next - get next value from a generator
177  * @gen: a generator state variable
178  *
179  * Returns a pointer to a (correctly typed) buffer containing the next
180  * value yielded by @gen, or NULL if @gen is finished.  The buffer
181  * contents is only valid until the next time @gen is called or
182  * manipulated.
183  */
184 static inline void *generator_next_(void *ret_)
185 {
186         struct generator_ *gen = generator_state_(ret_);
187
188         if (gen->complete)
189                 return NULL;
190
191         coroutine_switch(&gen->caller, &gen->gen);
192
193         return gen->complete ? NULL : ret_;
194 }
195 #define generator_next(gen_)                            \
196         ((generator_rtype_(gen_) *)generator_next_(gen_))
197
198 /**
199  * generator_next_val - store next value from a generator
200  * @val: a variable of type suitable to store the generator's return
201  *       type (lvalue)
202  * @gen: a generator state variable
203  *
204  * Returns 'true' if @gen yielded a new value, false if @gen is
205  * complete.  If a new value was yielded, it is stored in @val.
206  */
207 #define generator_next_val(val_, gen_)                  \
208         ({                                              \
209                 generator_rtype_(gen_) *ret;            \
210                 ret = generator_next(gen_);             \
211                 if (ret)                                \
212                         (val_) = *ret;                  \
213                 !!ret;                                  \
214         })
215
216 #define generator_free(gen_)                                    \
217         generator_free_((generator_rtype_(gen_) *)(gen_),       \
218                         sizeof(generator_rtype_(gen_)))
219
220 #endif /* CCAN_GENERATOR_H */