generator: Rewrite to use coroutine module
[ccan] / ccan / generator / generator.c
1 /* Licensed LGPLv2.1+ - see LICENSE file for details */
2 #include <stdlib.h>
3 #include <stdbool.h>
4 #include <stddef.h>
5
6 #include <ccan/alignof/alignof.h>
7
8 #include <ccan/generator/generator.h>
9
10 #define DEFAULT_STATE_SIZE      8192
11 #define STATE_ALIGN             ALIGNOF(struct generator_)
12
13 static size_t generator_metasize(size_t retsize)
14 {
15         retsize = (retsize + STATE_ALIGN) & ~(STATE_ALIGN - 1);
16         return sizeof(struct generator_) + retsize;
17 }
18
19 void *generator_new_(void (*fn)(void *), size_t retsize)
20 {
21         char *base;
22         size_t size = DEFAULT_STATE_SIZE;
23         size_t metasize = generator_metasize(retsize);
24         struct coroutine_stack *stack;
25         void *ret;
26         struct generator_ *gen;
27
28         base = malloc(size);
29         if (!base)
30                 abort();
31
32         retsize = (retsize + STATE_ALIGN) & ~(STATE_ALIGN - 1);
33
34         stack = coroutine_stack_init(base, size, metasize);
35         gen = coroutine_stack_to_metadata(stack, metasize);
36         ret = gen + 1;
37
38         gen->base = base;
39         gen->complete = false;
40
41         coroutine_init(&gen->gen, fn, ret, stack);
42
43         return ret;
44 }
45
46 void generator_free_(void *ret, size_t retsize)
47 {
48         struct generator_ *gen = generator_state_(ret);
49         size_t metasize = generator_metasize(retsize);
50         struct coroutine_stack *stack;
51
52         stack = coroutine_stack_from_metadata(gen, metasize);
53         coroutine_stack_release(stack, metasize);
54         free(gen->base);
55 }