Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pool.c
Go to the documentation of this file.
1 /*
2 ** pool.c - memory pool
3 **
4 ** See Copyright Notice in mruby.h
5 */
6 
7 #include <stddef.h>
8 #include <string.h>
9 #include "mruby.h"
10 
11 /* configuration section */
12 /* allocated memory address should be multiple of POOL_ALIGNMENT */
13 /* or undef it if alignment does not matter */
14 #ifndef POOL_ALIGNMENT
15 #define POOL_ALIGNMENT 4
16 #endif
17 /* page size of memory pool */
18 #ifndef POOL_PAGE_SIZE
19 #define POOL_PAGE_SIZE 16000
20 #endif
21 /* end of configuration section */
22 
23 struct mrb_pool_page {
25  size_t offset;
26  size_t len;
27  void *last;
28  char page[];
29 };
30 
31 struct mrb_pool {
34 };
35 
36 #undef TEST_POOL
37 #ifdef TEST_POOL
38 
39 #define mrb_malloc(m,s) malloc(s)
40 #define mrb_free(m,p) free(p)
41 #endif
42 
43 #ifdef POOL_ALIGNMENT
44 # define ALIGN_PADDING(x) ((-x) & (POOL_ALIGNMENT - 1))
45 #else
46 # define ALIGN_PADDING(x) (0)
47 #endif
48 
49 mrb_pool*
51 {
52  mrb_pool *pool = (mrb_pool *)mrb_malloc(mrb, sizeof(mrb_pool));
53 
54  if (pool) {
55  pool->mrb = mrb;
56  pool->pages = NULL;
57  }
58 
59  return pool;
60 }
61 
62 void
64 {
65  struct mrb_pool_page *page, *tmp;
66 
67  if (!pool) return;
68  page = pool->pages;
69  while (page) {
70  tmp = page;
71  page = page->next;
72  mrb_free(pool->mrb, tmp);
73  }
74  mrb_free(pool->mrb, pool);
75 }
76 
77 static struct mrb_pool_page*
78 page_alloc(mrb_pool *pool, size_t len)
79 {
80  struct mrb_pool_page *page;
81 
82  if (len < POOL_PAGE_SIZE)
83  len = POOL_PAGE_SIZE;
84  page = (struct mrb_pool_page *)mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len);
85  if (page) {
86  page->offset = 0;
87  page->len = len;
88  }
89 
90  return page;
91 }
92 
93 void*
94 mrb_pool_alloc(mrb_pool *pool, size_t len)
95 {
96  struct mrb_pool_page *page;
97  size_t n;
98 
99  if (!pool) return NULL;
100  len += ALIGN_PADDING(len);
101  page = pool->pages;
102  while (page) {
103  if (page->offset + len <= page->len) {
104  n = page->offset;
105  page->offset += len;
106  page->last = (char*)page->page+n;
107  return page->last;
108  }
109  page = page->next;
110  }
111  page = page_alloc(pool, len);
112  if (!page) return NULL;
113  page->offset = len;
114  page->next = pool->pages;
115  pool->pages = page;
116 
117  page->last = (void*)page->page;
118  return page->last;
119 }
120 
121 mrb_bool
122 mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len)
123 {
124  struct mrb_pool_page *page;
125 
126  if (!pool) return FALSE;
127  len += ALIGN_PADDING(len);
128  page = pool->pages;
129  while (page) {
130  if (page->last == p) {
131  size_t beg;
132 
133  beg = (char*)p - page->page;
134  if (beg + len > page->len) return FALSE;
135  return TRUE;
136  }
137  page = page->next;
138  }
139  return FALSE;
140 }
141 
142 void*
143 mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen)
144 {
145  struct mrb_pool_page *page;
146  void *np;
147 
148  if (!pool) return NULL;
149  oldlen += ALIGN_PADDING(oldlen);
150  newlen += ALIGN_PADDING(newlen);
151  page = pool->pages;
152  while (page) {
153  if (page->last == p) {
154  size_t beg;
155 
156  beg = (char*)p - page->page;
157  if (beg + oldlen != page->offset) break;
158  if (beg + newlen > page->len) {
159  page->offset = beg;
160  break;
161  }
162  page->offset = beg + newlen;
163  return p;
164  }
165  page = page->next;
166  }
167  np = mrb_pool_alloc(pool, newlen);
168  memcpy(np, p, oldlen);
169  return np;
170 }
171 
172 #ifdef TEST_POOL
173 int
174 main(void)
175 {
176  int i, len = 250;
177  mrb_pool *pool;
178  void *p;
179 
180  pool = mrb_pool_open(NULL);
181  p = mrb_pool_alloc(pool, len);
182  for (i=1; i<20; i++) {
183  printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2));
184  p = mrb_pool_realloc(pool, p, len, len*2);
185  len *= 2;
186  }
187  mrb_pool_close(pool);
188  return 0;
189 }
190 #endif