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>
28 * Internals - included just for the use of inlines and macros
38 static inline struct generator_ *generator_state_(const void *ret)
40 return (struct generator_ *)ret - 1;
43 struct generator_incomplete_;
45 #define generator_rtype_(gen_) \
46 typeof((*(gen_))((struct generator_incomplete_ *)NULL))
48 #if HAVE_POINTER_SAFE_MAKECONTEXT
49 #define generator_wrapper_args_() void *ret
51 #define generator_wrapper_args_() int lo, int hi
53 typedef void generator_wrapper_(generator_wrapper_args_());
55 void *generator_new_(generator_wrapper_ *fn, size_t retsize);
56 void generator_free_(void *ret);
63 * generator_t - type for an in-progress generator
64 * @rtype: type of values the generator yield
66 #define generator_t(rtype_) \
67 typeof(rtype_ (*)(struct generator_incomplete_ *))
70 * generator_declare - declare (but don't define) a generator function
71 * @name: name for the generator
72 * @rtype: return type for the generator
74 * Declares (as an extern) a generator function named @name, which
75 * will yield return values of type @rtype.
78 * generator_declare(count_to_3, int);
80 #define generator_declare(name_, rtype_) \
81 generator_t(rtype_) name_(void)
84 * generator_def - define a generator function
85 * @name: name for the generator
86 * @rtype: return type for the generator
88 * Define a generator function named @name yielding return values of
89 * type @rtype. The generator_def() line is followed immediately by a
90 * block containing the generator's code.
93 * generator_def(count_to_3, int)
100 #define generator_def_(name_, rtype_, storage_) \
101 static void name_##_generator_(rtype_ *ret_); \
102 static void name_##_generator__(generator_wrapper_args_()) \
104 struct generator_ *gen; \
105 CPPMAGIC_IFELSE(HAVE_POINTER_SAFE_MAKECONTEXT) \
107 (ptrdiff_t hilo = ((ptrdiff_t)hi << (8*sizeof(int))) \
109 rtype_ *ret = (rtype_ *)int2ptr(hilo); \
110 BUILD_ASSERT(sizeof(struct generator_ *) \
111 <= 2*sizeof(int));) \
112 gen = generator_state_(ret); \
113 name_##_generator_(ret); \
114 gen->complete = true; \
115 setcontext(&gen->caller); \
118 storage_ generator_t(rtype_) name_(void) \
120 return generator_new_(name_##_generator__, \
123 static void name_##_generator_(rtype_ *ret_)
124 #define generator_def(name_, rtype_) \
125 generator_def_(name_, rtype_, )
128 * generator_def_static - define a private / local generator function
129 * @name: name for the generator
130 * @rtype: return type for the generator
132 * As generator_def, but the resulting generator function will be
133 * local to this module.
135 #define generator_def_static(name_, rtype_) \
136 generator_def_(name_, rtype_, static)
139 * generator_yield - yield (return) a value from a generator
140 * @val: value to yield
142 * Invoke only from within a generator. Yield the given value to the
143 * caller. This will stop execution of the generator code until the
144 * caller next invokes generator_next(), at which point it will
145 * continue from the generator_yield statement.
147 #define generator_yield(val_) \
149 struct generator_ *gen_ = generator_state_(ret_); \
152 rc = swapcontext(&gen_->gen, &gen_->caller); \
157 * generator_next - get next value from a generator
158 * @gen: a generator state variable
160 * Returns a pointer to a (correctly typed) buffer containing the next
161 * value yielded by @gen, or NULL if @gen is finished. The buffer
162 * contents is only valid until the next time @gen is called or
165 static inline void *generator_next_(void *ret_)
167 struct generator_ *gen = generator_state_(ret_);
173 rc = swapcontext(&gen->caller, &gen->gen);
176 return gen->complete ? NULL : ret_;
178 #define generator_next(gen_) \
179 ((generator_rtype_(gen_) *)generator_next_(gen_))
182 * generator_next_val - store next value from a generator
183 * @val: a variable of type suitable to store the generator's return
185 * @gen: a generator state variable
187 * Returns 'true' if @gen yielded a new value, false if @gen is
188 * complete. If a new value was yielded, it is stored in @val.
190 #define generator_next_val(val_, gen_) \
192 generator_rtype_(gen_) *ret; \
193 ret = generator_next(gen_); \
199 #define generator_free(gen_) \
200 generator_free_((generator_rtype_(gen_) *)(gen_))
202 #endif /* CCAN_GENERATOR_H */