summaryrefslogtreecommitdiffhomepage
path: root/src/pool.c
diff options
context:
space:
mode:
authormimaki <[email protected]>2012-04-20 09:39:03 +0900
committermimaki <[email protected]>2012-04-20 09:39:03 +0900
commite0d6430f63c4cbe0c71ce82ee23284671389a818 (patch)
tree41abad7f12eced98d9ac14d141cea62464c3332f /src/pool.c
parent54ad561098ed353ada70205c39b2c42a2a2eb9e5 (diff)
downloadmruby-e0d6430f63c4cbe0c71ce82ee23284671389a818.tar.gz
mruby-e0d6430f63c4cbe0c71ce82ee23284671389a818.zip
add mruby sources
Diffstat (limited to 'src/pool.c')
-rw-r--r--src/pool.c152
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