@@ -29,121 +29,101 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
2929
3030class zone {
3131 struct finalizer {
32- finalizer(void (*func)(void*), void* data): m_func(func), m_data(data) {}
32+ finalizer(void (*func)(void*), void* data, finalizer* next): m_func(func), m_data(data), m_next(next ) {}
3333 void operator()() { m_func(m_data); }
3434 void (*m_func)(void*);
3535 void* m_data;
36+ finalizer* m_next;
3637 };
38+
3739 struct finalizer_array {
38- finalizer_array():m_tail(MSGPACK_NULLPTR), m_end(MSGPACK_NULLPTR), m_array(MSGPACK_NULLPTR) {}
39- void call() {
40- finalizer* fin = m_tail;
41- for(; fin != m_array; --fin) (*(fin-1))();
42- }
40+ finalizer_array(): m_head(MSGPACK_NULLPTR) {}
41+
4342 ~finalizer_array() {
44- call();
45- ::free(m_array);
46- }
47- void clear() {
48- call();
49- m_tail = m_array;
43+ clear();
5044 }
51- void push(void (*func)(void* data), void* data)
52- {
53- finalizer* fin = m_tail;
5445
55- if(fin == m_end) {
56- push_expand(func, data);
57- return;
46+ void clear() {
47+ finalizer* fin = m_head;
48+ finalizer* tmp = MSGPACK_NULLPTR;
49+ while(fin) {
50+ (*fin)();
51+ tmp = fin;
52+ fin = fin-> m_next;
53+ delete tmp;
5854 }
55+ m_head = MSGPACK_NULLPTR;
56+ }
5957
60- fin-> m_func = func;
61- fin-> m_data = data;
62-
63- ++m_tail;
58+ void push(void (*func)(void* data), void* data) {
59+ m_head = new finalizer(func, data, m_head);
6460 }
65- void push_expand(void (*func)(void*), void* data) {
66- const size_t nused = static_cast< size _t > (m_end - m_array);
67- size_t nnext;
68- if(nused == 0) {
69- nnext = (sizeof(finalizer) < 72 /2) ?
70- 72 / sizeof(finalizer) : 8;
71- } else {
72- nnext = nused * 2;
73- }
74- finalizer* tmp =
75- static_cast< finalizer * > (::realloc(m_array, sizeof(finalizer) * nnext));
76- if(!tmp) {
77- throw std::bad_alloc();
78- }
79- m_array = tmp;
80- m_end = tmp + nnext;
81- m_tail = tmp + nused;
82- new (m_tail) finalizer(func, data);
8361
84- ++m_tail;
62+ void pop() {
63+ finalizer* n = m_head-> m_next;
64+ delete m_head;
65+ m_head = n;
8566 }
86- finalizer* m_tail;
87- finalizer* m_end;
88- finalizer* m_array;
67+
68+ finalizer* m_head;
69+ private:
70+ finalizer_array(const finalizer_array&);
71+ finalizer_array& operator=(const finalizer_array&);
8972 };
73+
9074 struct chunk {
9175 chunk* m_next;
9276 };
93- struct chunk_list {
94- chunk_list(size_t chunk_size)
95- {
96- chunk* c = static_cast< chunk * > (::malloc(sizeof(chunk) + chunk_size));
97- if(!c) {
98- throw std::bad_alloc();
99- }
10077
101- m_head = c;
102- m_free = chunk_size;
103- m_ptr = reinterpret_cast< char * > (c) + sizeof(chunk);
104- c-> m_next = MSGPACK_NULLPTR;
105- }
106- ~chunk_list()
107- {
78+ struct chunk_list {
79+ chunk_list(size_t chunk_size, char* ptr): m_free(chunk_size), m_ptr(ptr), m_head(MSGPACK_NULLPTR) {}
80+ ~chunk_list() {
10881 chunk* c = m_head;
10982 while(c) {
11083 chunk* n = c-> m_next;
11184 ::free(c);
11285 c = n;
11386 }
87+ m_head = MSGPACK_NULLPTR;
11488 }
115- void clear(size_t chunk_size)
116- {
89+
90+ void clear(size_t chunk_size, char* ptr) {
11791 chunk* c = m_head;
118- while(true ) {
92+ while(c ) {
11993 chunk* n = c-> m_next;
120- if(n) {
121- ::free(c);
122- c = n;
123- } else {
124- m_head = c;
125- break;
126- }
94+ ::free(c);
95+ c = n;
12796 }
128- m_head- > m_next = MSGPACK_NULLPTR;
97+ m_head = MSGPACK_NULLPTR;
12998 m_free = chunk_size;
130- m_ptr = reinterpret_cast < char * > (m_head) + sizeof(chunk) ;
99+ m_ptr = ptr ;
131100 }
101+
132102 size_t m_free;
133103 char* m_ptr;
134104 chunk* m_head;
105+
106+ private:
107+ chunk_list(const chunk_list&);
108+ chunk_list& operator=(const chunk_list&);
135109 };
110+
136111 size_t m_chunk_size;
137- chunk_list m_chunk_list;
112+ chunk_list* m_chunk_list;
138113 finalizer_array m_finalizer_array;
139114
140115public:
141116 zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
117+ ~zone();
142118
143- public:
144119 void* allocate_align(size_t size, size_t align = MSGPACK_ZONE_ALIGN);
120+
145121 void* allocate_no_align(size_t size);
146122
123+ bool allocated() {
124+ return m_chunk_list != MSGPACK_NULLPTR;
125+ }
126+
147127 void push_finalizer(void (*func)(void*), void* data);
148128
149129 template < typename T >
@@ -152,24 +132,23 @@ public:
152132 void clear();
153133
154134 void swap(zone& o);
155- static void* operator new(std::size_t size)
156- {
135+
136+ static void* operator new(std::size_t size) {
157137 void* p = ::malloc(size);
158138 if (!p) throw std::bad_alloc();
159139 return p;
160140 }
161- static void operator delete(void *p) /* throw() */
162- {
141+
142+ static void operator delete(void *p) /* throw() */ {
163143 ::free(p);
164144 }
165- static void* operator new(std::size_t size, void* place) /* throw() */
166- {
167- return ::operator new(size, place);
168- }
169- static void operator delete(void* p, void* place) /* throw() */
170- {
171- ::operator delete(p, place);
145+
146+ static void* operator new(std::size_t /*size*/, void* mem) /* throw() */ {
147+ return mem;
172148 }
149+
150+ static void operator delete(void * /*p*/, void* /*mem*/) /* throw() */ {}
151+
173152 /// @cond
174153 <% 0 . upto ( GENERATION_LIMIT ) { |i |%>
175154 template < typename T<% 1 . upto ( i ) { |j |%> , typename A <%= j %> <% } %> >
@@ -188,56 +167,72 @@ private:
188167
189168 static char* get_aligned(char* ptr, size_t align);
190169
170+ chunk_list& get_chank_lst();
171+
191172 char* allocate_expand(size_t size);
192173private:
193174 zone(const zone&);
194175 zone& operator=(const zone&);
195176};
196177
197- inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(m_chunk_size)
198- {
178+ inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(MSGPACK_NULLPTR) {}
179+
180+ inline zone::~zone() {
181+ m_finalizer_array.~finalizer_array();
182+ if(m_chunk_list) {
183+ m_chunk_list-> ~chunk_list();
184+ ::free(m_chunk_list);
185+ m_chunk_list = MSGPACK_NULLPTR;
186+ }
199187}
200188
201- inline char* zone::get_aligned(char* ptr, size_t align)
202- {
189+ inline char* zone::get_aligned(char* ptr, size_t align) {
203190 MSGPACK_ASSERT(align != 0 && (align & (align - 1)) == 0); // align must be 2^n (n > = 0)
204191 return
205192 reinterpret_cast< char * > (
206193 reinterpret_cast< uintptr _t > (ptr + (align - 1)) & ~static_cast< uintptr _t > (align - 1)
207194 );
208195}
209196
210- inline void* zone::allocate_align(size_t size, size_t align)
211- {
212- char* aligned = get_aligned(m_chunk_list.m_ptr, align);
213- size_t adjusted_size = size + static_cast< size _t > (aligned - m_chunk_list.m_ptr);
214- if (m_chunk_list.m_free < adjusted _size) {
197+ inline zone::chunk_list& zone::get_chank_lst() {
198+ if (!m_chunk_list) {
199+ void* ptr = ::malloc(sizeof(chunk_list) + m_chunk_size);
200+ if (!ptr)
201+ throw std::bad_alloc();
202+ m_chunk_list = new (ptr) chunk_list(m_chunk_size, reinterpret_cast< char * > (ptr) + sizeof(chunk_list));
203+ }
204+ return *m_chunk_list;
205+ }
206+
207+ inline void* zone::allocate_align(size_t size, size_t align) {
208+ chunk_list& chank_lst = get_chank_lst();
209+ char* aligned = get_aligned(chank_lst.m_ptr, align);
210+ size_t adjusted_size = size + static_cast< size _t > (aligned - chank_lst.m_ptr);
211+ if (chank_lst.m_free < adjusted _size) {
215212 size_t enough_size = size + align - 1;
216213 char* ptr = allocate_expand(enough_size);
217214 aligned = get_aligned(ptr, align);
218- adjusted_size = size + static_cast < size _t > (aligned - m_chunk_list .m_ptr);
215+ adjusted_size = size + static_cast < size _t > (aligned - chank_lst .m_ptr);
219216 }
220- m_chunk_list .m_free -= adjusted_size;
221- m_chunk_list .m_ptr += adjusted_size;
217+ chank_lst .m_free -= adjusted_size;
218+ chank_lst .m_ptr += adjusted_size;
222219 return aligned;
223220}
224221
225- inline void* zone::allocate_no_align(size_t size)
226- {
227- char* ptr = m_chunk_list .m_ptr;
228- if(m_chunk_list .m_free < size ) {
222+ inline void* zone::allocate_no_align(size_t size) {
223+ chunk_list& chank_lst = get_chank_lst();
224+ char* ptr = chank_lst .m_ptr;
225+ if(chank_lst .m_free < size ) {
229226 ptr = allocate_expand(size);
230227 }
231- m_chunk_list .m_free - = size;
232- m_chunk_list .m_ptr + = size;
228+ chank_lst .m_free - = size;
229+ chank_lst .m_ptr + = size;
233230
234231 return ptr;
235232}
236233
237- inline char* zone::allocate_expand(size_t size)
238- {
239- chunk_list* const cl = &m_chunk_list;
240-
234+ inline char* zone::allocate_expand(size_t size) {
235+ chunk_list& cl = get_chank_lst();
241236 size_t sz = m_chunk_size;
242237
243238 while(sz < size ) {
@@ -254,60 +249,54 @@ inline char* zone::allocate_expand(size_t size)
254249
255250 char* ptr = reinterpret_cast< char * > (c) + sizeof(chunk);
256251
257- c-> m_next = cl- > m_head;
258- cl- > m_head = c;
259- cl- > m_free = sz;
260- cl- > m_ptr = ptr;
252+ c-> m_next = cl. m_head;
253+ cl. m_head = c;
254+ cl. m_free = sz;
255+ cl. m_ptr = ptr;
261256
262257 return ptr;
263258}
264259
265- inline void zone::push_finalizer(void (*func)(void*), void* data)
266- {
260+ inline void zone::push_finalizer(void (*func)(void*), void* data) {
267261 m_finalizer_array.push(func, data);
268262}
269263
270264template < typename T >
271- inline void zone::push_finalizer(msgpack::unique_ptr< T > obj)
272- {
265+ inline void zone::push_finalizer(msgpack::unique_ptr< T > obj) {
273266 m_finalizer_array.push(&zone::object_delete< T > , obj.release());
274267}
275268
276- inline void zone::clear()
277- {
269+ inline void zone::clear() {
278270 m_finalizer_array.clear();
279- m_chunk_list.clear(m_chunk_size);
271+ if (m_chunk_list) {
272+ m_chunk_list-> clear(m_chunk_size, reinterpret_cast< char * > (m_chunk_list) + sizeof(chunk_list));
273+ }
280274}
281275
282- inline void zone::swap(zone& o)
283- {
276+ inline void zone::swap(zone& o) {
284277 using std::swap;
285278 swap(m_chunk_size, o.m_chunk_size);
286279 swap(m_chunk_list, o.m_chunk_list);
287- swap(m_finalizer_array, o.m_finalizer_array);
280+ swap(m_finalizer_array.m_head , o.m_finalizer_array.m_head );
288281}
289282
290283template < typename T >
291- void zone::object_destruct(void* obj)
292- {
293- static_cast< T * > (obj)-> ~T();
284+ void zone::object_delete(void* obj) {
285+ delete static_cast< T * > (obj);
294286}
295287
296288template < typename T >
297- void zone::object_delete(void* obj)
298- {
299- delete static_cast< T * > (obj);
289+ void zone::object_destruct(void* obj) {
290+ static_cast< T * > (obj)-> ~T();
300291}
301292
302- inline void zone::undo_allocate(size_t size)
303- {
304- m_chunk_list .m_ptr -= size;
305- m_chunk_list .m_free += size;
293+ inline void zone::undo_allocate(size_t size) {
294+ chunk_list& cl = get_chank_lst();
295+ cl .m_ptr -= size;
296+ cl .m_free += size;
306297}
307298
308- inline std::size_t aligned_size(
309- std::size_t size,
310- std::size_t align) {
299+ inline std::size_t aligned_size(std::size_t size, std::size_t align) {
311300 return (size + align - 1) / align * align;
312301}
313302
@@ -326,7 +315,7 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
326315 try {
327316 return new (x) T(<%= ( 1 ..i ) . map { |j |"a#{ j } " } . join ( ', ' ) %> );
328317 } catch (...) {
329- -- m_finalizer_array.m_tail ;
318+ m_finalizer_array.pop() ;
330319 undo_allocate(sizeof(T));
331320 throw;
332321 }
0 commit comments