diff options
| author | mimaki <[email protected]> | 2012-04-20 09:39:03 +0900 |
|---|---|---|
| committer | mimaki <[email protected]> | 2012-04-20 09:39:03 +0900 |
| commit | e0d6430f63c4cbe0c71ce82ee23284671389a818 (patch) | |
| tree | 41abad7f12eced98d9ac14d141cea62464c3332f /src/pool.c | |
| parent | 54ad561098ed353ada70205c39b2c42a2a2eb9e5 (diff) | |
| download | mruby-e0d6430f63c4cbe0c71ce82ee23284671389a818.tar.gz mruby-e0d6430f63c4cbe0c71ce82ee23284671389a818.zip | |
add mruby sources
Diffstat (limited to 'src/pool.c')
| -rw-r--r-- | src/pool.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/pool.c b/src/pool.c new file mode 100644 index 000000000..62e1a4d17 --- /dev/null +++ b/src/pool.c @@ -0,0 +1,152 @@ +#include "pool.h" +#include <string.h> + +#undef TEST_POOL +#ifdef TEST_POOL +#include <stdio.h> + +#define mrb_malloc(m,s) malloc(s) +#define mrb_free(m,p) free(p) +#endif + +#define POOL_PAGE_SIZE 16000 + +mrb_pool* +mrb_pool_open(mrb_state *mrb) +{ + mrb_pool *pool = mrb_malloc(mrb, sizeof(mrb_pool)); + + if (pool) { + pool->mrb = mrb; + pool->pages = 0; + } + + return pool; +} + +void +mrb_pool_close(mrb_pool *pool) +{ + struct mrb_pool_page *page, *tmp; + + if (!pool) return; + page = pool->pages; + while (page) { + tmp = page; + page = page->next; + mrb_free(pool->mrb, tmp); + } + mrb_free(pool->mrb, pool); +} + +static struct mrb_pool_page* +page_alloc(mrb_pool *pool, size_t len) +{ + struct mrb_pool_page *page; + + if (len < POOL_PAGE_SIZE) + len = POOL_PAGE_SIZE; + page = mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len-1); + if (page) { + page->offset = 0; + page->len = len; + } + + return page; +} + +void* +mrb_pool_alloc(mrb_pool *pool, size_t len) +{ + struct mrb_pool_page *page; + size_t n; + + if (!pool) return 0; + + page = pool->pages; + while (page) { + if (page->offset + len <= page->len) { + n = page->offset; + page->offset += len; + page->last = (void*)page->page+n; + return page->last; + } + page = page->next; + } + page = page_alloc(pool, len); + if (!page) return 0; + page->offset = len; + page->next = pool->pages; + pool->pages = page; + + page->last = (void*)page->page; + return page->last; +} + +int +mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len) +{ + struct mrb_pool_page *page; + + if (!pool) return 0; + page = pool->pages; + while (page) { + if (page->last == p) { + size_t beg; + + beg = (char*)p - page->page; + if (beg + len > page->len) return 0; + return 1; + } + page = page->next; + } + return 0; +} + +void* +mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen) +{ + struct mrb_pool_page *page; + void *np; + + if (!pool) return 0; + page = pool->pages; + while (page) { + if (page->last == p) { + size_t beg; + + beg = (char*)p - page->page; + if (beg + oldlen != page->offset) break; + if (beg + newlen > page->len) { + page->offset = beg; + break; + } + page->offset = beg + newlen; + return p; + } + page = page->next; + } + np = mrb_pool_alloc(pool, newlen); + memcpy(np, p, oldlen); + return np; +} + +#ifdef TEST_POOL +int +main() +{ + int i, len = 250; + mrb_pool *pool; + void *p; + + pool = mrb_pool_open(0); + p = mrb_pool_alloc(pool, len); + for (i=1; i<20; i++) { + printf("%p (len=%d) %d\n", p, len, mrb_pool_can_realloc(pool, p, len*2)); + p = mrb_pool_realloc(pool, p, len, len*2); + len *= 2; + } + mrb_pool_close(pool); + return 0; +} +#endif |
