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