source: EcnlProtoTool/trunk/mruby-1.2.0/src/pool.c@ 321

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

文字コードを設定

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