mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
mbed-mruby
How to use
Class
src/pool.c@0:158c61bb030f, 2015-03-25 (annotated)
- Committer:
- mzta
- Date:
- Wed Mar 25 17:36:16 2015 +0000
- Revision:
- 0:158c61bb030f
mirb_mbed initial commit;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mzta | 0:158c61bb030f | 1 | /* |
mzta | 0:158c61bb030f | 2 | ** pool.c - memory pool |
mzta | 0:158c61bb030f | 3 | ** |
mzta | 0:158c61bb030f | 4 | ** See Copyright Notice in mruby.h |
mzta | 0:158c61bb030f | 5 | */ |
mzta | 0:158c61bb030f | 6 | |
mzta | 0:158c61bb030f | 7 | #include <stddef.h> |
mzta | 0:158c61bb030f | 8 | #include <stdint.h> |
mzta | 0:158c61bb030f | 9 | #include <string.h> |
mzta | 0:158c61bb030f | 10 | #include "mruby.h" |
mzta | 0:158c61bb030f | 11 | |
mzta | 0:158c61bb030f | 12 | /* configuration section */ |
mzta | 0:158c61bb030f | 13 | /* allocated memory address should be multiple of POOL_ALIGNMENT */ |
mzta | 0:158c61bb030f | 14 | /* or undef it if alignment does not matter */ |
mzta | 0:158c61bb030f | 15 | #ifndef POOL_ALIGNMENT |
mzta | 0:158c61bb030f | 16 | #define POOL_ALIGNMENT 4 |
mzta | 0:158c61bb030f | 17 | #endif |
mzta | 0:158c61bb030f | 18 | /* page size of memory pool */ |
mzta | 0:158c61bb030f | 19 | #ifndef POOL_PAGE_SIZE |
mzta | 0:158c61bb030f | 20 | #define POOL_PAGE_SIZE 16000 |
mzta | 0:158c61bb030f | 21 | #endif |
mzta | 0:158c61bb030f | 22 | /* end of configuration section */ |
mzta | 0:158c61bb030f | 23 | |
mzta | 0:158c61bb030f | 24 | struct mrb_pool_page { |
mzta | 0:158c61bb030f | 25 | struct mrb_pool_page *next; |
mzta | 0:158c61bb030f | 26 | size_t offset; |
mzta | 0:158c61bb030f | 27 | size_t len; |
mzta | 0:158c61bb030f | 28 | void *last; |
mzta | 0:158c61bb030f | 29 | char page[]; |
mzta | 0:158c61bb030f | 30 | }; |
mzta | 0:158c61bb030f | 31 | |
mzta | 0:158c61bb030f | 32 | struct mrb_pool { |
mzta | 0:158c61bb030f | 33 | mrb_state *mrb; |
mzta | 0:158c61bb030f | 34 | struct mrb_pool_page *pages; |
mzta | 0:158c61bb030f | 35 | }; |
mzta | 0:158c61bb030f | 36 | |
mzta | 0:158c61bb030f | 37 | #undef TEST_POOL |
mzta | 0:158c61bb030f | 38 | #ifdef TEST_POOL |
mzta | 0:158c61bb030f | 39 | |
mzta | 0:158c61bb030f | 40 | #define mrb_malloc_simple(m,s) malloc(s) |
mzta | 0:158c61bb030f | 41 | #define mrb_free(m,p) free(p) |
mzta | 0:158c61bb030f | 42 | #endif |
mzta | 0:158c61bb030f | 43 | |
mzta | 0:158c61bb030f | 44 | #ifdef POOL_ALIGNMENT |
mzta | 0:158c61bb030f | 45 | # define ALIGN_PADDING(x) ((SIZE_MAX - (x) + 1) & (POOL_ALIGNMENT - 1)) |
mzta | 0:158c61bb030f | 46 | #else |
mzta | 0:158c61bb030f | 47 | # define ALIGN_PADDING(x) (0) |
mzta | 0:158c61bb030f | 48 | #endif |
mzta | 0:158c61bb030f | 49 | |
mzta | 0:158c61bb030f | 50 | MRB_API mrb_pool* |
mzta | 0:158c61bb030f | 51 | mrb_pool_open(mrb_state *mrb) |
mzta | 0:158c61bb030f | 52 | { |
mzta | 0:158c61bb030f | 53 | mrb_pool *pool = (mrb_pool *)mrb_malloc_simple(mrb, sizeof(mrb_pool)); |
mzta | 0:158c61bb030f | 54 | |
mzta | 0:158c61bb030f | 55 | if (pool) { |
mzta | 0:158c61bb030f | 56 | pool->mrb = mrb; |
mzta | 0:158c61bb030f | 57 | pool->pages = NULL; |
mzta | 0:158c61bb030f | 58 | } |
mzta | 0:158c61bb030f | 59 | |
mzta | 0:158c61bb030f | 60 | return pool; |
mzta | 0:158c61bb030f | 61 | } |
mzta | 0:158c61bb030f | 62 | |
mzta | 0:158c61bb030f | 63 | MRB_API void |
mzta | 0:158c61bb030f | 64 | mrb_pool_close(mrb_pool *pool) |
mzta | 0:158c61bb030f | 65 | { |
mzta | 0:158c61bb030f | 66 | struct mrb_pool_page *page, *tmp; |
mzta | 0:158c61bb030f | 67 | |
mzta | 0:158c61bb030f | 68 | if (!pool) return; |
mzta | 0:158c61bb030f | 69 | page = pool->pages; |
mzta | 0:158c61bb030f | 70 | while (page) { |
mzta | 0:158c61bb030f | 71 | tmp = page; |
mzta | 0:158c61bb030f | 72 | page = page->next; |
mzta | 0:158c61bb030f | 73 | mrb_free(pool->mrb, tmp); |
mzta | 0:158c61bb030f | 74 | } |
mzta | 0:158c61bb030f | 75 | mrb_free(pool->mrb, pool); |
mzta | 0:158c61bb030f | 76 | } |
mzta | 0:158c61bb030f | 77 | |
mzta | 0:158c61bb030f | 78 | static struct mrb_pool_page* |
mzta | 0:158c61bb030f | 79 | page_alloc(mrb_pool *pool, size_t len) |
mzta | 0:158c61bb030f | 80 | { |
mzta | 0:158c61bb030f | 81 | struct mrb_pool_page *page; |
mzta | 0:158c61bb030f | 82 | |
mzta | 0:158c61bb030f | 83 | if (len < POOL_PAGE_SIZE) |
mzta | 0:158c61bb030f | 84 | len = POOL_PAGE_SIZE; |
mzta | 0:158c61bb030f | 85 | page = (struct mrb_pool_page *)mrb_malloc_simple(pool->mrb, sizeof(struct mrb_pool_page)+len); |
mzta | 0:158c61bb030f | 86 | if (page) { |
mzta | 0:158c61bb030f | 87 | page->offset = 0; |
mzta | 0:158c61bb030f | 88 | page->len = len; |
mzta | 0:158c61bb030f | 89 | } |
mzta | 0:158c61bb030f | 90 | |
mzta | 0:158c61bb030f | 91 | return page; |
mzta | 0:158c61bb030f | 92 | } |
mzta | 0:158c61bb030f | 93 | |
mzta | 0:158c61bb030f | 94 | MRB_API void* |
mzta | 0:158c61bb030f | 95 | mrb_pool_alloc(mrb_pool *pool, size_t len) |
mzta | 0:158c61bb030f | 96 | { |
mzta | 0:158c61bb030f | 97 | struct mrb_pool_page *page; |
mzta | 0:158c61bb030f | 98 | size_t n; |
mzta | 0:158c61bb030f | 99 | |
mzta | 0:158c61bb030f | 100 | if (!pool) return NULL; |
mzta | 0:158c61bb030f | 101 | len += ALIGN_PADDING(len); |
mzta | 0:158c61bb030f | 102 | page = pool->pages; |
mzta | 0:158c61bb030f | 103 | while (page) { |
mzta | 0:158c61bb030f | 104 | if (page->offset + len <= page->len) { |
mzta | 0:158c61bb030f | 105 | n = page->offset; |
mzta | 0:158c61bb030f | 106 | page->offset += len; |
mzta | 0:158c61bb030f | 107 | page->last = (char*)page->page+n; |
mzta | 0:158c61bb030f | 108 | return page->last; |
mzta | 0:158c61bb030f | 109 | } |
mzta | 0:158c61bb030f | 110 | page = page->next; |
mzta | 0:158c61bb030f | 111 | } |
mzta | 0:158c61bb030f | 112 | page = page_alloc(pool, len); |
mzta | 0:158c61bb030f | 113 | if (!page) return NULL; |
mzta | 0:158c61bb030f | 114 | page->offset = len; |
mzta | 0:158c61bb030f | 115 | page->next = pool->pages; |
mzta | 0:158c61bb030f | 116 | pool->pages = page; |
mzta | 0:158c61bb030f | 117 | |
mzta | 0:158c61bb030f | 118 | page->last = (void*)page->page; |
mzta | 0:158c61bb030f | 119 | return page->last; |
mzta | 0:158c61bb030f | 120 | } |
mzta | 0:158c61bb030f | 121 | |
mzta | 0:158c61bb030f | 122 | MRB_API mrb_bool |
mzta | 0:158c61bb030f | 123 | mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len) |
mzta | 0:158c61bb030f | 124 | { |
mzta | 0:158c61bb030f | 125 | struct mrb_pool_page *page; |
mzta | 0:158c61bb030f | 126 | |
mzta | 0:158c61bb030f | 127 | if (!pool) return FALSE; |
mzta | 0:158c61bb030f | 128 | len += ALIGN_PADDING(len); |
mzta | 0:158c61bb030f | 129 | page = pool->pages; |
mzta | 0:158c61bb030f | 130 | while (page) { |
mzta | 0:158c61bb030f | 131 | if (page->last == p) { |
mzta | 0:158c61bb030f | 132 | size_t beg; |
mzta | 0:158c61bb030f | 133 | |
mzta | 0:158c61bb030f | 134 | beg = (char*)p - page->page; |
mzta | 0:158c61bb030f | 135 | if (beg + len > page->len) return FALSE; |
mzta | 0:158c61bb030f | 136 | return TRUE; |
mzta | 0:158c61bb030f | 137 | } |
mzta | 0:158c61bb030f | 138 | page = page->next; |
mzta | 0:158c61bb030f | 139 | } |
mzta | 0:158c61bb030f | 140 | return FALSE; |
mzta | 0:158c61bb030f | 141 | } |
mzta | 0:158c61bb030f | 142 | |
mzta | 0:158c61bb030f | 143 | MRB_API void* |
mzta | 0:158c61bb030f | 144 | mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen) |
mzta | 0:158c61bb030f | 145 | { |
mzta | 0:158c61bb030f | 146 | struct mrb_pool_page *page; |
mzta | 0:158c61bb030f | 147 | void *np; |
mzta | 0:158c61bb030f | 148 | |
mzta | 0:158c61bb030f | 149 | if (!pool) return NULL; |
mzta | 0:158c61bb030f | 150 | oldlen += ALIGN_PADDING(oldlen); |
mzta | 0:158c61bb030f | 151 | newlen += ALIGN_PADDING(newlen); |
mzta | 0:158c61bb030f | 152 | page = pool->pages; |
mzta | 0:158c61bb030f | 153 | while (page) { |
mzta | 0:158c61bb030f | 154 | if (page->last == p) { |
mzta | 0:158c61bb030f | 155 | size_t beg; |
mzta | 0:158c61bb030f | 156 | |
mzta | 0:158c61bb030f | 157 | beg = (char*)p - page->page; |
mzta | 0:158c61bb030f | 158 | if (beg + oldlen != page->offset) break; |
mzta | 0:158c61bb030f | 159 | if (beg + newlen > page->len) { |
mzta | 0:158c61bb030f | 160 | page->offset = beg; |
mzta | 0:158c61bb030f | 161 | break; |
mzta | 0:158c61bb030f | 162 | } |
mzta | 0:158c61bb030f | 163 | page->offset = beg + newlen; |
mzta | 0:158c61bb030f | 164 | return p; |
mzta | 0:158c61bb030f | 165 | } |
mzta | 0:158c61bb030f | 166 | page = page->next; |
mzta | 0:158c61bb030f | 167 | } |
mzta | 0:158c61bb030f | 168 | np = mrb_pool_alloc(pool, newlen); |
mzta | 0:158c61bb030f | 169 | if (np == NULL) { |
mzta | 0:158c61bb030f | 170 | return NULL; |
mzta | 0:158c61bb030f | 171 | } |
mzta | 0:158c61bb030f | 172 | memcpy(np, p, oldlen); |
mzta | 0:158c61bb030f | 173 | return np; |
mzta | 0:158c61bb030f | 174 | } |
mzta | 0:158c61bb030f | 175 | |
mzta | 0:158c61bb030f | 176 | #ifdef TEST_POOL |
mzta | 0:158c61bb030f | 177 | int |
mzta | 0:158c61bb030f | 178 | main(void) |
mzta | 0:158c61bb030f | 179 | { |
mzta | 0:158c61bb030f | 180 | int i, len = 250; |
mzta | 0:158c61bb030f | 181 | mrb_pool *pool; |
mzta | 0:158c61bb030f | 182 | void *p; |
mzta | 0:158c61bb030f | 183 | |
mzta | 0:158c61bb030f | 184 | pool = mrb_pool_open(NULL); |
mzta | 0:158c61bb030f | 185 | p = mrb_pool_alloc(pool, len); |
mzta | 0:158c61bb030f | 186 | for (i=1; i<20; i++) { |
mzta | 0:158c61bb030f | 187 | printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2)); |
mzta | 0:158c61bb030f | 188 | p = mrb_pool_realloc(pool, p, len, len*2); |
mzta | 0:158c61bb030f | 189 | len *= 2; |
mzta | 0:158c61bb030f | 190 | } |
mzta | 0:158c61bb030f | 191 | mrb_pool_close(pool); |
mzta | 0:158c61bb030f | 192 | return 0; |
mzta | 0:158c61bb030f | 193 | } |
mzta | 0:158c61bb030f | 194 | #endif |
mzta | 0:158c61bb030f | 195 |