2 ** pool.c - memory pool
4 ** See Copyright Notice in mruby.h
12 /* configuration section */
13 /* allocated memory address should be multiple of POOL_ALIGNMENT */
14 /* or undef it if alignment does not matter */
15 #ifndef POOL_ALIGNMENT
16 #if INTPTR_MAX == INT64_MAX
17 #define POOL_ALIGNMENT 8
19 #define POOL_ALIGNMENT 4
22 /* page size of memory pool */
23 #ifndef POOL_PAGE_SIZE
24 #define POOL_PAGE_SIZE 16000
26 /* end of configuration section */
28 /* Disable MSVC warning "C4200: nonstandard extension used: zero-sized array
29 * in struct/union" when in C++ mode */
32 #pragma warning(disable : 4200)
35 struct mrb_pool_page {
36 struct mrb_pool_page *next;
49 struct mrb_pool_page *pages;
55 #define mrb_malloc_simple(m,s) malloc(s)
56 #define mrb_free(m,p) free(p)
60 # define ALIGN_PADDING(x) ((SIZE_MAX - (x) + 1) & (POOL_ALIGNMENT - 1))
62 # define ALIGN_PADDING(x) (0)
66 mrb_pool_open(mrb_state *mrb)
68 mrb_pool *pool = (mrb_pool *)mrb_malloc_simple(mrb, sizeof(mrb_pool));
79 mrb_pool_close(mrb_pool *pool)
81 struct mrb_pool_page *page, *tmp;
88 mrb_free(pool->mrb, tmp);
90 mrb_free(pool->mrb, pool);
93 static struct mrb_pool_page*
94 page_alloc(mrb_pool *pool, size_t len)
96 struct mrb_pool_page *page;
98 if (len < POOL_PAGE_SIZE)
100 page = (struct mrb_pool_page *)mrb_malloc_simple(pool->mrb, sizeof(struct mrb_pool_page)+len);
110 mrb_pool_alloc(mrb_pool *pool, size_t len)
112 struct mrb_pool_page *page;
115 if (!pool) return NULL;
116 len += ALIGN_PADDING(len);
119 if (page->offset + len <= page->len) {
122 page->last = (char*)page->page+n;
127 page = page_alloc(pool, len);
128 if (!page) return NULL;
130 page->next = pool->pages;
133 page->last = (void*)page->page;
138 mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len)
140 struct mrb_pool_page *page;
142 if (!pool) return FALSE;
143 len += ALIGN_PADDING(len);
146 if (page->last == p) {
149 beg = (char*)p - page->page;
150 if (beg + len > page->len) return FALSE;
159 mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen)
161 struct mrb_pool_page *page;
164 if (!pool) return NULL;
165 oldlen += ALIGN_PADDING(oldlen);
166 newlen += ALIGN_PADDING(newlen);
169 if (page->last == p) {
172 beg = (char*)p - page->page;
173 if (beg + oldlen != page->offset) break;
174 if (beg + newlen > page->len) {
178 page->offset = beg + newlen;
183 np = mrb_pool_alloc(pool, newlen);
187 memcpy(np, p, oldlen);
199 pool = mrb_pool_open(NULL);
200 p = mrb_pool_alloc(pool, len);
201 for (i=1; i<20; i++) {
202 printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2));
203 p = mrb_pool_realloc(pool, p, len, len*2);
206 mrb_pool_close(pool);