2 ** pool.c - memory pool
4 ** See Copyright Notice in mruby.h
10 /* configuration section */
11 /* allocated memory address should be multiple of POOL_ALIGNMENT */
12 /* or undef it if alignment does not matter */
13 #ifndef POOL_ALIGNMENT
14 #if INTPTR_MAX == INT64_MAX
15 #define POOL_ALIGNMENT 8
17 #define POOL_ALIGNMENT 4
20 /* page size of memory pool */
21 #ifndef POOL_PAGE_SIZE
22 #define POOL_PAGE_SIZE 16000
24 /* end of configuration section */
26 /* Disable MSVC warning "C4200: nonstandard extension used: zero-sized array
27 * in struct/union" when in C++ mode */
30 #pragma warning(disable : 4200)
33 struct mrb_pool_page {
34 struct mrb_pool_page *next;
47 struct mrb_pool_page *pages;
53 #define mrb_malloc_simple(m,s) malloc(s)
54 #define mrb_free(m,p) free(p)
58 # define ALIGN_PADDING(x) ((SIZE_MAX - (x) + 1) & (POOL_ALIGNMENT - 1))
60 # define ALIGN_PADDING(x) (0)
64 mrb_pool_open(mrb_state *mrb)
66 mrb_pool *pool = (mrb_pool *)mrb_malloc_simple(mrb, sizeof(mrb_pool));
77 mrb_pool_close(mrb_pool *pool)
79 struct mrb_pool_page *page, *tmp;
86 mrb_free(pool->mrb, tmp);
88 mrb_free(pool->mrb, pool);
91 static struct mrb_pool_page*
92 page_alloc(mrb_pool *pool, size_t len)
94 struct mrb_pool_page *page;
96 if (len < POOL_PAGE_SIZE)
98 page = (struct mrb_pool_page *)mrb_malloc_simple(pool->mrb, sizeof(struct mrb_pool_page)+len);
108 mrb_pool_alloc(mrb_pool *pool, size_t len)
110 struct mrb_pool_page *page;
113 if (!pool) return NULL;
114 len += ALIGN_PADDING(len);
117 if (page->offset + len <= page->len) {
120 page->last = (char*)page->page+n;
125 page = page_alloc(pool, len);
126 if (!page) return NULL;
128 page->next = pool->pages;
131 page->last = (void*)page->page;
136 mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len)
138 struct mrb_pool_page *page;
140 if (!pool) return FALSE;
141 len += ALIGN_PADDING(len);
144 if (page->last == p) {
147 beg = (char*)p - page->page;
148 if (beg + len > page->len) return FALSE;
157 mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen)
159 struct mrb_pool_page *page;
162 if (!pool) return NULL;
163 oldlen += ALIGN_PADDING(oldlen);
164 newlen += ALIGN_PADDING(newlen);
167 if (page->last == p) {
170 beg = (char*)p - page->page;
171 if (beg + oldlen != page->offset) break;
172 if (beg + newlen > page->len) {
176 page->offset = beg + newlen;
181 np = mrb_pool_alloc(pool, newlen);
185 memcpy(np, p, oldlen);
197 pool = mrb_pool_open(NULL);
198 p = mrb_pool_alloc(pool, len);
199 for (i=1; i<20; i++) {
200 printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2));
201 p = mrb_pool_realloc(pool, p, len, len*2);
204 mrb_pool_close(pool);