1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
2 #ifndef CCAN_GENERATOR_H
3 #define CCAN_GENERATOR_H
7 #error Generators require working ucontext.h functions
11 #error Generators require typeof
14 #if !HAVE_STATEMENT_EXPR
15 #error Generators require statement expressions
23 #include <ccan/ptrint/ptrint.h>
24 #include <ccan/build_assert/build_assert.h>
25 #include <ccan/cppmagic/cppmagic.h>
26 #include <ccan/compiler/compiler.h>
29 * Internals - included just for the use of inlines and macros
39 static inline struct generator_ *generator_state_(const void *ret)
41 return (struct generator_ *)ret - 1;
44 static inline void *generator_argp_(const void *ret)
46 return generator_state_(ret)->base;
49 struct generator_incomplete_;
51 #define generator_rtype_(gen_) \
52 typeof((*(gen_))((struct generator_incomplete_ *)NULL))
54 #if HAVE_POINTER_SAFE_MAKECONTEXT
55 #define generator_wrapper_args_() void *ret
57 #define generator_wrapper_args_() int lo, int hi
59 typedef void generator_wrapper_(generator_wrapper_args_());
61 void *generator_new_(generator_wrapper_ *fn, size_t retsize);
62 void generator_free_(void *ret);
69 * generator_t - type for an in-progress generator
70 * @rtype: type of values the generator yield
72 #define generator_t(rtype_) \
73 typeof(rtype_ (*)(struct generator_incomplete_ *))
76 * generator_declare - declare (but don't define) a generator function
77 * @name: name for the generator
78 * @rtype: return type for the generator
80 * Declares (as an extern) a generator function named @name, which
81 * will yield return values of type @rtype.
84 * generator_declare(count_to_3, int);
86 #define generator_declare(name_, rtype_, ...) \
87 generator_t(rtype_) name_(generator_parms_outer_(__VA_ARGS__))
90 * generator_def - define a generator function
91 * @name: name for the generator
92 * @rtype: return type for the generator
94 * Define a generator function named @name yielding return values of
95 * type @rtype. The generator_def() line is followed immediately by a
96 * block containing the generator's code.
99 * generator_def(count_to_3, int)
101 * generator_yield(1);
102 * generator_yield(2);
103 * generator_yield(3);
106 #define generator_parm_(t_, n_) t_ n_
107 #define generator_parms_(...) \
108 CPPMAGIC_2MAP(generator_parm_, __VA_ARGS__)
109 #define generator_parms_inner_(...) \
110 CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
111 (, generator_parms_(__VA_ARGS__))()
112 #define generator_parms_outer_(...) \
113 CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
114 (generator_parms_(__VA_ARGS__))(void)
115 #define generator_argfield_(t_, n_) t_ n_;
116 #define generator_argstruct_(...) \
118 CPPMAGIC_JOIN(, CPPMAGIC_2MAP(generator_argfield_, \
121 #define generator_arg_unpack_(t_, n_) args->n_
122 #define generator_args_unpack_(...) \
123 CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
124 (, CPPMAGIC_2MAP(generator_arg_unpack_, __VA_ARGS__))()
125 #define generator_arg_pack_(t_, n_) args->n_ = n_
126 #define generator_args_pack_(...) \
127 CPPMAGIC_JOIN(;, CPPMAGIC_2MAP(generator_arg_pack_, __VA_ARGS__))
128 #define generator_def_(name_, rtype_, storage_, ...) \
129 static void name_##_generator_(rtype_ *ret_ \
130 generator_parms_inner_(__VA_ARGS__)); \
131 static void name_##_generator__(generator_wrapper_args_()) \
133 struct generator_ *gen; \
134 UNNEEDED generator_argstruct_(__VA_ARGS__) *args; \
135 CPPMAGIC_IFELSE(HAVE_POINTER_SAFE_MAKECONTEXT) \
137 (ptrdiff_t hilo = ((ptrdiff_t)hi << (8*sizeof(int))) \
139 rtype_ *ret = (rtype_ *)int2ptr(hilo); \
140 BUILD_ASSERT(sizeof(struct generator_ *) \
141 <= 2*sizeof(int));) \
142 gen = generator_state_(ret); \
143 args = generator_argp_(ret); \
144 name_##_generator_(ret generator_args_unpack_(__VA_ARGS__)); \
145 gen->complete = true; \
146 setcontext(&gen->caller); \
149 storage_ generator_t(rtype_) \
150 name_(generator_parms_outer_(__VA_ARGS__)) \
152 generator_t(rtype_) gen = generator_new_(name_##_generator__, \
154 UNNEEDED generator_argstruct_(__VA_ARGS__) *args = \
155 generator_argp_(gen); \
156 generator_args_pack_(__VA_ARGS__); \
159 static void name_##_generator_(rtype_ *ret_ \
160 generator_parms_inner_(__VA_ARGS__))
161 #define generator_def(name_, rtype_, ...) \
162 generator_def_(name_, rtype_, , __VA_ARGS__)
165 * generator_def_static - define a private / local generator function
166 * @name: name for the generator
167 * @rtype: return type for the generator
169 * As generator_def, but the resulting generator function will be
170 * local to this module.
172 #define generator_def_static(name_, rtype_, ...) \
173 generator_def_(name_, rtype_, static, __VA_ARGS__)
176 * generator_yield - yield (return) a value from a generator
177 * @val: value to yield
179 * Invoke only from within a generator. Yield the given value to the
180 * caller. This will stop execution of the generator code until the
181 * caller next invokes generator_next(), at which point it will
182 * continue from the generator_yield statement.
184 #define generator_yield(val_) \
186 struct generator_ *gen_ = generator_state_(ret_); \
189 rc = swapcontext(&gen_->gen, &gen_->caller); \
194 * generator_next - get next value from a generator
195 * @gen: a generator state variable
197 * Returns a pointer to a (correctly typed) buffer containing the next
198 * value yielded by @gen, or NULL if @gen is finished. The buffer
199 * contents is only valid until the next time @gen is called or
202 static inline void *generator_next_(void *ret_)
204 struct generator_ *gen = generator_state_(ret_);
210 rc = swapcontext(&gen->caller, &gen->gen);
213 return gen->complete ? NULL : ret_;
215 #define generator_next(gen_) \
216 ((generator_rtype_(gen_) *)generator_next_(gen_))
219 * generator_next_val - store next value from a generator
220 * @val: a variable of type suitable to store the generator's return
222 * @gen: a generator state variable
224 * Returns 'true' if @gen yielded a new value, false if @gen is
225 * complete. If a new value was yielded, it is stored in @val.
227 #define generator_next_val(val_, gen_) \
229 generator_rtype_(gen_) *ret; \
230 ret = generator_next(gen_); \
236 #define generator_free(gen_) \
237 generator_free_((generator_rtype_(gen_) *)(gen_))
239 #endif /* CCAN_GENERATOR_H */