mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pool.c Source File

pool.c

00001 /*
00002 ** pool.c - memory pool
00003 **
00004 ** See Copyright Notice in mruby.h
00005 */
00006 
00007 #include <stddef.h>
00008 #include <stdint.h>
00009 #include <string.h>
00010 #include "mruby.h"
00011 
00012 /* configuration section */
00013 /* allocated memory address should be multiple of POOL_ALIGNMENT */
00014 /* or undef it if alignment does not matter */
00015 #ifndef POOL_ALIGNMENT
00016 #define POOL_ALIGNMENT 4
00017 #endif
00018 /* page size of memory pool */
00019 #ifndef POOL_PAGE_SIZE
00020 #define POOL_PAGE_SIZE 16000
00021 #endif
00022 /* end of configuration section */
00023 
00024 struct mrb_pool_page {
00025   struct mrb_pool_page *next;
00026   size_t offset;
00027   size_t len;
00028   void *last;
00029   char page[];
00030 };
00031 
00032 struct mrb_pool {
00033   mrb_state *mrb;
00034   struct mrb_pool_page *pages;
00035 };
00036 
00037 #undef TEST_POOL
00038 #ifdef TEST_POOL
00039 
00040 #define mrb_malloc_simple(m,s) malloc(s)
00041 #define mrb_free(m,p) free(p)
00042 #endif
00043 
00044 #ifdef POOL_ALIGNMENT
00045 #  define ALIGN_PADDING(x) ((SIZE_MAX - (x) + 1) & (POOL_ALIGNMENT - 1))
00046 #else
00047 #  define ALIGN_PADDING(x) (0)
00048 #endif
00049 
00050 MRB_API mrb_pool*
00051 mrb_pool_open(mrb_state *mrb)
00052 {
00053   mrb_pool *pool = (mrb_pool *)mrb_malloc_simple(mrb, sizeof(mrb_pool));
00054 
00055   if (pool) {
00056     pool->mrb = mrb;
00057     pool->pages = NULL;
00058   }
00059 
00060   return pool;
00061 }
00062 
00063 MRB_API void
00064 mrb_pool_close(mrb_pool *pool)
00065 {
00066   struct mrb_pool_page *page, *tmp;
00067 
00068   if (!pool) return;
00069   page = pool->pages;
00070   while (page) {
00071     tmp = page;
00072     page = page->next;
00073     mrb_free(pool->mrb, tmp);
00074   }
00075   mrb_free(pool->mrb, pool);
00076 }
00077 
00078 static struct mrb_pool_page*
00079 page_alloc(mrb_pool *pool, size_t len)
00080 {
00081   struct mrb_pool_page *page;
00082 
00083   if (len < POOL_PAGE_SIZE)
00084     len = POOL_PAGE_SIZE;
00085   page = (struct mrb_pool_page *)mrb_malloc_simple(pool->mrb, sizeof(struct mrb_pool_page)+len);
00086   if (page) {
00087     page->offset = 0;
00088     page->len = len;
00089   }
00090 
00091   return page;
00092 }
00093 
00094 MRB_API void*
00095 mrb_pool_alloc(mrb_pool *pool, size_t len)
00096 {
00097   struct mrb_pool_page *page;
00098   size_t n;
00099 
00100   if (!pool) return NULL;
00101   len += ALIGN_PADDING(len);
00102   page = pool->pages;
00103   while (page) {
00104     if (page->offset + len <= page->len) {
00105       n = page->offset;
00106       page->offset += len;
00107       page->last = (char*)page->page+n;
00108       return page->last;
00109     }
00110     page = page->next;
00111   }
00112   page = page_alloc(pool, len);
00113   if (!page) return NULL;
00114   page->offset = len;
00115   page->next = pool->pages;
00116   pool->pages = page;
00117 
00118   page->last = (void*)page->page;
00119   return page->last;
00120 }
00121 
00122 MRB_API mrb_bool
00123 mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len)
00124 {
00125   struct mrb_pool_page *page;
00126 
00127   if (!pool) return FALSE;
00128   len += ALIGN_PADDING(len);
00129   page = pool->pages;
00130   while (page) {
00131     if (page->last == p) {
00132       size_t beg;
00133 
00134       beg = (char*)p - page->page;
00135       if (beg + len > page->len) return FALSE;
00136       return TRUE;
00137     }
00138     page = page->next;
00139   }
00140   return FALSE;
00141 }
00142 
00143 MRB_API void*
00144 mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen)
00145 {
00146   struct mrb_pool_page *page;
00147   void *np;
00148 
00149   if (!pool) return NULL;
00150   oldlen += ALIGN_PADDING(oldlen);
00151   newlen += ALIGN_PADDING(newlen);
00152   page = pool->pages;
00153   while (page) {
00154     if (page->last == p) {
00155       size_t beg;
00156 
00157       beg = (char*)p - page->page;
00158       if (beg + oldlen != page->offset) break;
00159       if (beg + newlen > page->len) {
00160         page->offset = beg;
00161         break;
00162       }
00163       page->offset = beg + newlen;
00164       return p;
00165     }
00166     page = page->next;
00167   }
00168   np = mrb_pool_alloc(pool, newlen);
00169   if (np == NULL) {
00170     return NULL;
00171   }
00172   memcpy(np, p, oldlen);
00173   return np;
00174 }
00175 
00176 #ifdef TEST_POOL
00177 int
00178 main(void)
00179 {
00180   int i, len = 250;
00181   mrb_pool *pool;
00182   void *p;
00183 
00184   pool = mrb_pool_open(NULL);
00185   p = mrb_pool_alloc(pool, len);
00186   for (i=1; i<20; i++) {
00187     printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2));
00188     p = mrb_pool_realloc(pool, p, len, len*2);
00189     len *= 2;
00190   }
00191   mrb_pool_close(pool);
00192   return 0;
00193 }
00194 #endif
00195