source: EcnlProtoTool/trunk/mruby-2.1.1/src/pool.c@ 439

Last change on this file since 439 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 3.9 KB
Line 
1/*
2** pool.c - memory pool
3**
4** See Copyright Notice in mruby.h
5*/
6
7#include <string.h>
8#include <mruby.h>
9
10/* configuration section */
11/* allocated memory address should be multiple of POOL_ALIGNMENT */
12/* or undef it if alignment does not matter */
13#ifndef POOL_ALIGNMENT
14#if INTPTR_MAX == INT64_MAX
15#define POOL_ALIGNMENT 8
16#else
17#define POOL_ALIGNMENT 4
18#endif
19#endif
20/* page size of memory pool */
21#ifndef POOL_PAGE_SIZE
22#define POOL_PAGE_SIZE 16000
23#endif
24/* end of configuration section */
25
26/* Disable MSVC warning "C4200: nonstandard extension used: zero-sized array
27 * in struct/union" when in C++ mode */
28#ifdef _MSC_VER
29#pragma warning(push)
30#pragma warning(disable : 4200)
31#endif
32
33struct mrb_pool_page {
34 struct mrb_pool_page *next;
35 size_t offset;
36 size_t len;
37 void *last;
38 char page[];
39};
40
41#ifdef _MSC_VER
42#pragma warning(pop)
43#endif
44
45struct mrb_pool {
46 mrb_state *mrb;
47 struct mrb_pool_page *pages;
48};
49
50#undef TEST_POOL
51#ifdef TEST_POOL
52
53#define mrb_malloc_simple(m,s) malloc(s)
54#define mrb_free(m,p) free(p)
55#endif
56
57#ifdef POOL_ALIGNMENT
58# define ALIGN_PADDING(x) ((SIZE_MAX - (x) + 1) & (POOL_ALIGNMENT - 1))
59#else
60# define ALIGN_PADDING(x) (0)
61#endif
62
63MRB_API mrb_pool*
64mrb_pool_open(mrb_state *mrb)
65{
66 mrb_pool *pool = (mrb_pool *)mrb_malloc_simple(mrb, sizeof(mrb_pool));
67
68 if (pool) {
69 pool->mrb = mrb;
70 pool->pages = NULL;
71 }
72
73 return pool;
74}
75
76MRB_API void
77mrb_pool_close(mrb_pool *pool)
78{
79 struct mrb_pool_page *page, *tmp;
80
81 if (!pool) return;
82 page = pool->pages;
83 while (page) {
84 tmp = page;
85 page = page->next;
86 mrb_free(pool->mrb, tmp);
87 }
88 mrb_free(pool->mrb, pool);
89}
90
91static struct mrb_pool_page*
92page_alloc(mrb_pool *pool, size_t len)
93{
94 struct mrb_pool_page *page;
95
96 if (len < POOL_PAGE_SIZE)
97 len = POOL_PAGE_SIZE;
98 page = (struct mrb_pool_page *)mrb_malloc_simple(pool->mrb, sizeof(struct mrb_pool_page)+len);
99 if (page) {
100 page->offset = 0;
101 page->len = len;
102 }
103
104 return page;
105}
106
107MRB_API void*
108mrb_pool_alloc(mrb_pool *pool, size_t len)
109{
110 struct mrb_pool_page *page;
111 size_t n;
112
113 if (!pool) return NULL;
114 len += ALIGN_PADDING(len);
115 page = pool->pages;
116 while (page) {
117 if (page->offset + len <= page->len) {
118 n = page->offset;
119 page->offset += len;
120 page->last = (char*)page->page+n;
121 return page->last;
122 }
123 page = page->next;
124 }
125 page = page_alloc(pool, len);
126 if (!page) return NULL;
127 page->offset = len;
128 page->next = pool->pages;
129 pool->pages = page;
130
131 page->last = (void*)page->page;
132 return page->last;
133}
134
135MRB_API mrb_bool
136mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len)
137{
138 struct mrb_pool_page *page;
139
140 if (!pool) return FALSE;
141 len += ALIGN_PADDING(len);
142 page = pool->pages;
143 while (page) {
144 if (page->last == p) {
145 size_t beg;
146
147 beg = (char*)p - page->page;
148 if (beg + len > page->len) return FALSE;
149 return TRUE;
150 }
151 page = page->next;
152 }
153 return FALSE;
154}
155
156MRB_API void*
157mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen)
158{
159 struct mrb_pool_page *page;
160 void *np;
161
162 if (!pool) return NULL;
163 oldlen += ALIGN_PADDING(oldlen);
164 newlen += ALIGN_PADDING(newlen);
165 page = pool->pages;
166 while (page) {
167 if (page->last == p) {
168 size_t beg;
169
170 beg = (char*)p - page->page;
171 if (beg + oldlen != page->offset) break;
172 if (beg + newlen > page->len) {
173 page->offset = beg;
174 break;
175 }
176 page->offset = beg + newlen;
177 return p;
178 }
179 page = page->next;
180 }
181 np = mrb_pool_alloc(pool, newlen);
182 if (np == NULL) {
183 return NULL;
184 }
185 memcpy(np, p, oldlen);
186 return np;
187}
188
189#ifdef TEST_POOL
190int
191main(void)
192{
193 int i, len = 250;
194 mrb_pool *pool;
195 void *p;
196
197 pool = mrb_pool_open(NULL);
198 p = mrb_pool_alloc(pool, len);
199 for (i=1; i<20; i++) {
200 printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2));
201 p = mrb_pool_realloc(pool, p, len, len*2);
202 len *= 2;
203 }
204 mrb_pool_close(pool);
205 return 0;
206}
207#endif
Note: See TracBrowser for help on using the repository browser.