@@ -29,101 +29,121 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
29
29
30
30
class zone {
31
31
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) {}
33
33
void operator()() { m_func(m_data); }
34
34
void (*m_func)(void*);
35
35
void* m_data;
36
- finalizer* m_next;
37
36
};
38
-
39
37
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
+ }
42
43
~finalizer_array() {
43
- clear();
44
+ call();
45
+ ::free(m_array);
44
46
}
45
-
46
47
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;
56
50
}
51
+ void push(void (*func)(void* data), void* data)
52
+ {
53
+ finalizer* fin = m_tail;
57
54
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;
61
62
62
- void pop() {
63
- finalizer* n = m_head-> m_next;
64
- delete m_head;
65
- m_head = n;
63
+ ++m_tail;
66
64
}
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);
67
83
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;
72
89
};
73
-
74
90
struct chunk {
75
91
chunk* m_next;
76
92
};
77
-
78
93
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
+ {
81
108
chunk* c = m_head;
82
109
while(c) {
83
110
chunk* n = c-> m_next;
84
111
::free(c);
85
112
c = n;
86
113
}
87
- m_head = MSGPACK_NULLPTR;
88
114
}
89
-
90
- void clear(size_t chunk_size, char* ptr) {
115
+ void clear(size_t chunk_size)
116
+ {
91
117
chunk* c = m_head;
92
- while(c ) {
118
+ while(true ) {
93
119
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
+ }
96
127
}
97
- m_head = MSGPACK_NULLPTR;
128
+ m_head- > m_next = MSGPACK_NULLPTR;
98
129
m_free = chunk_size;
99
- m_ptr = ptr ;
130
+ m_ptr = reinterpret_cast < char * > (m_head) + sizeof(chunk) ;
100
131
}
101
-
102
132
size_t m_free;
103
133
char* m_ptr;
104
134
chunk* m_head;
105
-
106
- private:
107
- chunk_list(const chunk_list&);
108
- chunk_list& operator=(const chunk_list&);
109
135
};
110
-
111
136
size_t m_chunk_size;
112
- chunk_list* m_chunk_list;
137
+ chunk_list m_chunk_list;
113
138
finalizer_array m_finalizer_array;
114
139
115
140
public:
116
141
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
117
- ~zone();
118
142
143
+ public:
119
144
void* allocate_align(size_t size, size_t align = MSGPACK_ZONE_ALIGN);
120
-
121
145
void* allocate_no_align(size_t size);
122
146
123
- bool allocated() {
124
- return m_chunk_list != MSGPACK_NULLPTR;
125
- }
126
-
127
147
void push_finalizer(void (*func)(void*), void* data);
128
148
129
149
template < typename T >
@@ -132,23 +152,24 @@ public:
132
152
void clear();
133
153
134
154
void swap(zone& o);
135
-
136
- static void* operator new(std::size_t size) {
155
+ static void* operator new(std::size_t size)
156
+ {
137
157
void* p = ::malloc(size);
138
158
if (!p) throw std::bad_alloc();
139
159
return p;
140
160
}
141
-
142
- static void operator delete(void *p) /* throw() */ {
161
+ static void operator delete(void *p) /* throw() */
162
+ {
143
163
::free(p);
144
164
}
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);
148
172
}
149
-
150
- static void operator delete(void * /*p*/, void* /*mem*/) /* throw() */ {}
151
-
152
173
/// @cond
153
174
<% 0 . upto ( GENERATION_LIMIT ) { |i |%>
154
175
template < typename T<% 1 . upto ( i ) { |j |%> , typename A <%= j %> <% } %> >
@@ -167,72 +188,56 @@ private:
167
188
168
189
static char* get_aligned(char* ptr, size_t align);
169
190
170
- chunk_list& get_chank_lst();
171
-
172
191
char* allocate_expand(size_t size);
173
192
private:
174
193
zone(const zone&);
175
194
zone& operator=(const zone&);
176
195
};
177
196
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
+ {
187
199
}
188
200
189
- inline char* zone::get_aligned(char* ptr, size_t align) {
201
+ inline char* zone::get_aligned(char* ptr, size_t align)
202
+ {
190
203
MSGPACK_ASSERT(align != 0 && (align & (align - 1)) == 0); // align must be 2^n (n > = 0)
191
204
return
192
205
reinterpret_cast< char * > (
193
206
reinterpret_cast< uintptr _t > (ptr + (align - 1)) & ~static_cast< uintptr _t > (align - 1)
194
207
);
195
208
}
196
209
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) {
212
215
size_t enough_size = size + align - 1;
213
216
char* ptr = allocate_expand(enough_size);
214
217
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);
216
219
}
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;
219
222
return aligned;
220
223
}
221
224
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 ) {
226
229
ptr = allocate_expand(size);
227
230
}
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;
230
233
231
234
return ptr;
232
235
}
233
236
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
+
236
241
size_t sz = m_chunk_size;
237
242
238
243
while(sz < size ) {
@@ -249,54 +254,60 @@ inline char* zone::allocate_expand(size_t size) {
249
254
250
255
char* ptr = reinterpret_cast< char * > (c) + sizeof(chunk);
251
256
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;
256
261
257
262
return ptr;
258
263
}
259
264
260
- inline void zone::push_finalizer(void (*func)(void*), void* data) {
265
+ inline void zone::push_finalizer(void (*func)(void*), void* data)
266
+ {
261
267
m_finalizer_array.push(func, data);
262
268
}
263
269
264
270
template < 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
+ {
266
273
m_finalizer_array.push(&zone::object_delete< T > , obj.release());
267
274
}
268
275
269
- inline void zone::clear() {
276
+ inline void zone::clear()
277
+ {
270
278
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);
274
280
}
275
281
276
- inline void zone::swap(zone& o) {
282
+ inline void zone::swap(zone& o)
283
+ {
277
284
using std::swap;
278
285
swap(m_chunk_size, o.m_chunk_size);
279
286
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);
281
288
}
282
289
283
290
template < 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();
286
294
}
287
295
288
296
template < 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);
291
300
}
292
301
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;
297
306
}
298
307
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) {
300
311
return (size + align - 1) / align * align;
301
312
}
302
313
@@ -315,7 +326,7 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
315
326
try {
316
327
return new (x) T(<%= ( 1 ..i ) . map { |j |"a#{ j } " } . join ( ', ' ) %> );
317
328
} catch (...) {
318
- m_finalizer_array.pop() ;
329
+ -- m_finalizer_array.m_tail ;
319
330
undo_allocate(sizeof(T));
320
331
throw;
321
332
}
0 commit comments