@@ -29,101 +29,121 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
2929
3030class zone {
3131 struct finalizer {
32- finalizer(void (*func)(void*), void* data, finalizer* next): m_func(func), m_data(data), m_next(next ) {}
32+ finalizer(void (*func)(void*), void* data): m_func(func), m_data(data) {}
3333 void operator()() { m_func(m_data); }
3434 void (*m_func)(void*);
3535 void* m_data;
36- finalizer* m_next;
3736 };
38-
3937 struct finalizer_array {
40- finalizer_array(): m_head(MSGPACK_NULLPTR) {}
41-
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+ }
4243 ~finalizer_array() {
43- clear();
44+ call();
45+ ::free(m_array);
4446 }
45-
4647 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;
54- }
55- m_head = MSGPACK_NULLPTR;
48+ call();
49+ m_tail = m_array;
5650 }
51+ void push(void (*func)(void* data), void* data)
52+ {
53+ finalizer* fin = m_tail;
5754
58- void push(void (*func)(void* data), void* data) {
59- m_head = new finalizer(func, data, m_head);
60- }
55+ if(fin == m_end) {
56+ push_expand(func, data);
57+ return;
58+ }
59+
60+ fin-> m_func = func;
61+ fin-> m_data = data;
6162
62- void pop() {
63- finalizer* n = m_head-> m_next;
64- delete m_head;
65- m_head = n;
63+ ++m_tail;
6664 }
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);
6783
68- finalizer* m_head;
69- private:
70- finalizer_array(const finalizer_array&);
71- finalizer_array& operator=(const finalizer_array&);
84+ ++m_tail;
85+ }
86+ finalizer* m_tail;
87+ finalizer* m_end;
88+ finalizer* m_array;
7289 };
73-
7490 struct chunk {
7591 chunk* m_next;
7692 };
77-
7893 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() {
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+ }
100+
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+ {
81108 chunk* c = m_head;
82109 while(c) {
83110 chunk* n = c-> m_next;
84111 ::free(c);
85112 c = n;
86113 }
87- m_head = MSGPACK_NULLPTR;
88114 }
89-
90- void clear(size_t chunk_size, char* ptr) {
115+ void clear(size_t chunk_size)
116+ {
91117 chunk* c = m_head;
92- while(c ) {
118+ while(true ) {
93119 chunk* n = c-> m_next;
94- ::free(c);
95- c = n;
120+ if(n) {
121+ ::free(c);
122+ c = n;
123+ } else {
124+ m_head = c;
125+ break;
126+ }
96127 }
97- m_head = MSGPACK_NULLPTR;
128+ m_head- > m_next = MSGPACK_NULLPTR;
98129 m_free = chunk_size;
99- m_ptr = ptr ;
130+ m_ptr = reinterpret_cast < char * > (m_head) + sizeof(chunk) ;
100131 }
101-
102132 size_t m_free;
103133 char* m_ptr;
104134 chunk* m_head;
105-
106- private:
107- chunk_list(const chunk_list&);
108- chunk_list& operator=(const chunk_list&);
109135 };
110-
111136 size_t m_chunk_size;
112- chunk_list* m_chunk_list;
137+ chunk_list m_chunk_list;
113138 finalizer_array m_finalizer_array;
114139
115140public:
116141 zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
117- ~zone();
118142
143+ public:
119144 void* allocate_align(size_t size, size_t align = MSGPACK_ZONE_ALIGN);
120-
121145 void* allocate_no_align(size_t size);
122146
123- bool allocated() {
124- return m_chunk_list != MSGPACK_NULLPTR;
125- }
126-
127147 void push_finalizer(void (*func)(void*), void* data);
128148
129149 template < typename T >
@@ -132,23 +152,24 @@ public:
132152 void clear();
133153
134154 void swap(zone& o);
135-
136- static void* operator new(std::size_t size) {
155+ static void* operator new(std::size_t size)
156+ {
137157 void* p = ::malloc(size);
138158 if (!p) throw std::bad_alloc();
139159 return p;
140160 }
141-
142- static void operator delete(void *p) /* throw() */ {
161+ static void operator delete(void *p) /* throw() */
162+ {
143163 ::free(p);
144164 }
145-
146- static void* operator new(std::size_t /*size*/, void* mem) /* throw() */ {
147- return mem;
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);
148172 }
149-
150- static void operator delete(void * /*p*/, void* /*mem*/) /* throw() */ {}
151-
152173 /// @cond
153174 <% 0 . upto ( GENERATION_LIMIT ) { |i |%>
154175 template < typename T<% 1 . upto ( i ) { |j |%> , typename A <%= j %> <% } %> >
@@ -167,72 +188,56 @@ private:
167188
168189 static char* get_aligned(char* ptr, size_t align);
169190
170- chunk_list& get_chank_lst();
171-
172191 char* allocate_expand(size_t size);
173192private:
174193 zone(const zone&);
175194 zone& operator=(const zone&);
176195};
177196
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- }
197+ inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(m_chunk_size)
198+ {
187199}
188200
189- inline char* zone::get_aligned(char* ptr, size_t align) {
201+ inline char* zone::get_aligned(char* ptr, size_t align)
202+ {
190203 MSGPACK_ASSERT(align != 0 && (align & (align - 1)) == 0); // align must be 2^n (n > = 0)
191204 return
192205 reinterpret_cast< char * > (
193206 reinterpret_cast< uintptr _t > (ptr + (align - 1)) & ~static_cast< uintptr _t > (align - 1)
194207 );
195208}
196209
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) {
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) {
212215 size_t enough_size = size + align - 1;
213216 char* ptr = allocate_expand(enough_size);
214217 aligned = get_aligned(ptr, align);
215- adjusted_size = size + static_cast < size _t > (aligned - chank_lst .m_ptr);
218+ adjusted_size = size + static_cast < size _t > (aligned - m_chunk_list .m_ptr);
216219 }
217- chank_lst .m_free -= adjusted_size;
218- chank_lst .m_ptr += adjusted_size;
220+ m_chunk_list .m_free -= adjusted_size;
221+ m_chunk_list .m_ptr += adjusted_size;
219222 return aligned;
220223}
221224
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 ) {
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 ) {
226229 ptr = allocate_expand(size);
227230 }
228- chank_lst .m_free - = size;
229- chank_lst .m_ptr + = size;
231+ m_chunk_list .m_free - = size;
232+ m_chunk_list .m_ptr + = size;
230233
231234 return ptr;
232235}
233236
234- inline char* zone::allocate_expand(size_t size) {
235- chunk_list& cl = get_chank_lst();
237+ inline char* zone::allocate_expand(size_t size)
238+ {
239+ chunk_list* const cl = &m_chunk_list;
240+
236241 size_t sz = m_chunk_size;
237242
238243 while(sz < size ) {
@@ -249,54 +254,60 @@ inline char* zone::allocate_expand(size_t size) {
249254
250255 char* ptr = reinterpret_cast< char * > (c) + sizeof(chunk);
251256
252- c-> m_next = cl. m_head;
253- cl. m_head = c;
254- cl. m_free = sz;
255- cl. m_ptr = ptr;
257+ c-> m_next = cl- > m_head;
258+ cl- > m_head = c;
259+ cl- > m_free = sz;
260+ cl- > m_ptr = ptr;
256261
257262 return ptr;
258263}
259264
260- inline void zone::push_finalizer(void (*func)(void*), void* data) {
265+ inline void zone::push_finalizer(void (*func)(void*), void* data)
266+ {
261267 m_finalizer_array.push(func, data);
262268}
263269
264270template < typename T >
265- inline void zone::push_finalizer(msgpack::unique_ptr< T > obj) {
271+ inline void zone::push_finalizer(msgpack::unique_ptr< T > obj)
272+ {
266273 m_finalizer_array.push(&zone::object_delete< T > , obj.release());
267274}
268275
269- inline void zone::clear() {
276+ inline void zone::clear()
277+ {
270278 m_finalizer_array.clear();
271- if (m_chunk_list) {
272- m_chunk_list-> clear(m_chunk_size, reinterpret_cast< char * > (m_chunk_list) + sizeof(chunk_list));
273- }
279+ m_chunk_list.clear(m_chunk_size);
274280}
275281
276- inline void zone::swap(zone& o) {
282+ inline void zone::swap(zone& o)
283+ {
277284 using std::swap;
278285 swap(m_chunk_size, o.m_chunk_size);
279286 swap(m_chunk_list, o.m_chunk_list);
280- swap(m_finalizer_array.m_head , o.m_finalizer_array.m_head );
287+ swap(m_finalizer_array, o.m_finalizer_array);
281288}
282289
283290template < typename T >
284- void zone::object_delete(void* obj) {
285- delete static_cast< T * > (obj);
291+ void zone::object_destruct(void* obj)
292+ {
293+ static_cast< T * > (obj)-> ~T();
286294}
287295
288296template < typename T >
289- void zone::object_destruct(void* obj) {
290- static_cast< T * > (obj)-> ~T();
297+ void zone::object_delete(void* obj)
298+ {
299+ delete static_cast< T * > (obj);
291300}
292301
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;
302+ inline void zone::undo_allocate(size_t size)
303+ {
304+ m_chunk_list .m_ptr -= size;
305+ m_chunk_list .m_free += size;
297306}
298307
299- inline std::size_t aligned_size(std::size_t size, std::size_t align) {
308+ inline std::size_t aligned_size(
309+ std::size_t size,
310+ std::size_t align) {
300311 return (size + align - 1) / align * align;
301312}
302313
@@ -315,7 +326,7 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
315326 try {
316327 return new (x) T(<%= ( 1 ..i ) . map { |j |"a#{ j } " } . join ( ', ' ) %> );
317328 } catch (...) {
318- m_finalizer_array.pop() ;
329+ -- m_finalizer_array.m_tail ;
319330 undo_allocate(sizeof(T));
320331 throw;
321332 }
0 commit comments