@@ -25,81 +25,59 @@ namespace msgpack {
2525// / @cond
2626MSGPACK_API_VERSION_NAMESPACE (v1) {
2727// / @endcond
28-
28+
2929class zone {
3030private:
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 };
3738 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 ))();
39+ finalizer_array (): m_head(MSGPACK_NULLPTR) {}
40+
41+ void call (bool clear = false ) {
42+ finalizer* fin = m_head;
43+ finalizer* tmp = nullptr ;
44+ while (fin) {
45+ (*(fin-1 ))();
46+ if (clear) {
47+ tmp = fin;
48+ }
49+ fin = fin->m_next ;
50+ if (clear) {
51+ delete tmp;
52+ }
53+ }
4254 }
4355 ~finalizer_array () {
44- call ();
45- ::free (m_array);
56+ call (true );
4657 }
4758 void clear () {
48- call ();
49- m_tail = m_array;
59+ call (true );
5060 }
5161 void push (void (*func)(void * data), void* data)
5262 {
53- finalizer* fin = m_tail;
54-
55- if (fin == m_end) {
56- push_expand (func, data);
57- return ;
58- }
59-
60- fin->m_func = func;
61- fin->m_data = data;
62-
63- ++m_tail;
63+ m_head = new finalizer (func, data, m_head);
6464 }
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-
84- ++m_tail;
65+ void pop () {
66+ auto n = m_head->m_next ;
67+ delete m_head;
68+ m_head = n;
8569 }
86- finalizer_array (finalizer_array&& other) noexcept
87- :m_tail(other.m_tail), m_end(other.m_end), m_array(other.m_array)
88- {
89- other.m_tail = MSGPACK_NULLPTR;
90- other.m_end = MSGPACK_NULLPTR;
91- other.m_array = MSGPACK_NULLPTR;
70+
71+ finalizer_array (finalizer_array&& other) noexcept : m_head(other.m_head) {
72+ other.m_head = MSGPACK_NULLPTR;
9273 }
9374 finalizer_array& operator =(finalizer_array&& other) noexcept
9475 {
9576 this ->~finalizer_array ();
9677 new (this ) finalizer_array (std::move (other));
9778 return *this ;
9879 }
99-
100- finalizer* m_tail;
101- finalizer* m_end;
102- finalizer* m_array;
80+ finalizer* m_head;
10381
10482 private:
10583 finalizer_array (const finalizer_array&);
@@ -109,69 +87,44 @@ class zone {
10987 chunk* m_next;
11088 };
11189 struct chunk_list {
112- chunk_list (size_t chunk_size)
113- {
114- chunk* c = static_cast <chunk*>(::malloc (sizeof (chunk) + chunk_size));
115- if (!c) {
116- throw std::bad_alloc ();
117- }
118-
119- m_head = c;
120- m_free = chunk_size;
121- m_ptr = reinterpret_cast <char *>(c) + sizeof (chunk);
122- c->m_next = MSGPACK_NULLPTR;
123- }
124- ~chunk_list ()
125- {
90+ chunk_list (size_t chunk_size, char * ptr): m_free(chunk_size), m_ptr(ptr), m_head(MSGPACK_NULLPTR) {}
91+ ~chunk_list () {
12692 chunk* c = m_head;
12793 while (c) {
12894 chunk* n = c->m_next ;
12995 ::free (c);
13096 c = n;
13197 }
13298 }
133- void clear (size_t chunk_size)
99+ void clear (size_t chunk_size, char * ptr )
134100 {
135101 chunk* c = m_head;
136- while (true ) {
102+ while (c ) {
137103 chunk* n = c->m_next ;
138- if (n) {
139- ::free (c);
140- c = n;
141- } else {
142- m_head = c;
143- break ;
144- }
104+ ::free (c);
105+ c = n;
145106 }
146107 m_head->m_next = MSGPACK_NULLPTR;
147108 m_free = chunk_size;
148- m_ptr = reinterpret_cast <char *>(m_head) + sizeof (chunk);
149- }
150- chunk_list (chunk_list&& other) noexcept
151- :m_free(other.m_free), m_ptr(other.m_ptr), m_head(other.m_head)
152- {
153- other.m_head = MSGPACK_NULLPTR;
154- }
155- chunk_list& operator =(chunk_list&& other) noexcept
156- {
157- this ->~chunk_list ();
158- new (this ) chunk_list (std::move (other));
159- return *this ;
109+ m_ptr = ptr;
160110 }
161111
162112 size_t m_free;
163113 char * m_ptr;
164114 chunk* m_head;
165115 private:
116+ chunk_list (chunk_list&& other) noexcept = delete ;
117+ chunk_list& operator =(chunk_list&& other) noexcept = delete ;
166118 chunk_list (const chunk_list&);
167119 chunk_list& operator =(const chunk_list&);
168120 };
169121 size_t m_chunk_size;
170- chunk_list m_chunk_list;
122+ chunk_list* m_chunk_list{} ;
171123 finalizer_array m_finalizer_array;
172124
173125public:
174126 zone (size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
127+ ~zone ();
175128
176129public:
177130 void * allocate_align (size_t size, size_t align = MSGPACK_ZONE_ALIGN);
@@ -223,53 +176,75 @@ class zone {
223176
224177 static char * get_aligned (char * ptr, size_t align);
225178
179+ chunk_list& get_chank_lst ();
180+
226181 char * allocate_expand (size_t size);
227182};
228183
229- inline zone::zone (size_t chunk_size):m_chunk_size (chunk_size), m_chunk_list (m_chunk_size)
184+ inline zone::zone (size_t chunk_size):m_chunk_size (chunk_size), m_chunk_list (MSGPACK_NULLPTR)
185+ {
186+ }
187+
188+ inline zone::~zone ()
230189{
190+ if (m_chunk_list) {
191+ m_chunk_list->~chunk_list ();
192+ ::free (m_chunk_list);
193+ m_chunk_list = MSGPACK_NULLPTR;
194+ }
231195}
232196
233197inline char * zone::get_aligned (char * ptr, size_t align)
234198{
235199 MSGPACK_ASSERT (align != 0 && (align & (align - 1 )) == 0 ); // align must be 2^n (n >= 0)
236200 return
237- reinterpret_cast <char *>(
238- reinterpret_cast <uintptr_t >(ptr + (align - 1 )) & ~static_cast <uintptr_t >(align - 1 )
239- );
201+ reinterpret_cast <char *>(
202+ reinterpret_cast <uintptr_t >(ptr + (align - 1 )) & ~static_cast <uintptr_t >(align - 1 )
203+ );
204+ }
205+
206+ inline zone::chunk_list& zone::get_chank_lst ()
207+ {
208+ if (!m_chunk_list) {
209+ auto ptr = ::malloc (sizeof (chunk_list) + m_chunk_size);
210+ if (!ptr)
211+ throw std::bad_alloc ();
212+ m_chunk_list = new (ptr) chunk_list (m_chunk_size, reinterpret_cast <char *>(ptr) + sizeof (chunk_list));
213+ }
214+ return *m_chunk_list;
240215}
241216
242217inline void * zone::allocate_align (size_t size, size_t align)
243218{
244- char * aligned = get_aligned (m_chunk_list.m_ptr , align);
245- size_t adjusted_size = size + static_cast <size_t >(aligned - m_chunk_list.m_ptr );
246- if (m_chunk_list.m_free < adjusted_size) {
219+ chunk_list& chank_lst = get_chank_lst ();
220+ char * aligned = get_aligned (chank_lst.m_ptr , align);
221+ size_t adjusted_size = size + static_cast <size_t >(aligned - chank_lst.m_ptr );
222+ if (chank_lst.m_free < adjusted_size) {
247223 size_t enough_size = size + align - 1 ;
248224 char * ptr = allocate_expand (enough_size);
249225 aligned = get_aligned (ptr, align);
250- adjusted_size = size + static_cast <size_t >(aligned - m_chunk_list .m_ptr );
226+ adjusted_size = size + static_cast <size_t >(aligned - chank_lst .m_ptr );
251227 }
252- m_chunk_list .m_free -= adjusted_size;
253- m_chunk_list .m_ptr += adjusted_size;
228+ chank_lst .m_free -= adjusted_size;
229+ chank_lst .m_ptr += adjusted_size;
254230 return aligned;
255231}
256232
257- inline void * zone::allocate_no_align (size_t size)
258- {
259- char * ptr = m_chunk_list .m_ptr ;
260- if (m_chunk_list .m_free < size) {
233+ inline void * zone::allocate_no_align (size_t size) {
234+ chunk_list& chank_lst = get_chank_lst ();
235+ char * ptr = chank_lst .m_ptr ;
236+ if (chank_lst .m_free < size) {
261237 ptr = allocate_expand (size);
262238 }
263- m_chunk_list .m_free -= size;
264- m_chunk_list .m_ptr += size;
239+ chank_lst .m_free -= size;
240+ chank_lst .m_ptr += size;
265241
266242 return ptr;
267243}
268244
269245inline char * zone::allocate_expand (size_t size)
270246{
271- chunk_list* const cl = &m_chunk_list;
272-
247+ chunk_list& cl = get_chank_lst ();
273248 size_t sz = m_chunk_size;
274249
275250 while (sz < size) {
@@ -286,10 +261,10 @@ inline char* zone::allocate_expand(size_t size)
286261
287262 char * ptr = reinterpret_cast <char *>(c) + sizeof (chunk);
288263
289- c->m_next = cl-> m_head ;
290- cl-> m_head = c;
291- cl-> m_free = sz;
292- cl-> m_ptr = ptr;
264+ c->m_next = cl. m_head ;
265+ cl. m_head = c;
266+ cl. m_free = sz;
267+ cl. m_ptr = ptr;
293268
294269 return ptr;
295270}
@@ -308,7 +283,9 @@ inline void zone::push_finalizer(msgpack::unique_ptr<T> obj)
308283inline void zone::clear ()
309284{
310285 m_finalizer_array.clear ();
311- m_chunk_list.clear (m_chunk_size);
286+ if (m_chunk_list) {
287+ m_chunk_list->clear (m_chunk_size, reinterpret_cast <char *>(m_chunk_list) + sizeof (chunk_list));
288+ }
312289}
313290
314291inline void zone::swap (zone& o)
@@ -328,10 +305,10 @@ void zone::object_destruct(void* obj)
328305 static_cast <T*>(obj)->~T ();
329306}
330307
331- inline void zone::undo_allocate (size_t size)
332- {
333- m_chunk_list .m_ptr -= size;
334- m_chunk_list .m_free += size;
308+ inline void zone::undo_allocate (size_t size) {
309+ chunk_list& cl = get_chank_lst ();
310+ cl .m_ptr -= size;
311+ cl .m_free += size;
335312}
336313
337314
@@ -348,7 +325,7 @@ T* zone::allocate(Args... args)
348325 try {
349326 return new (x) T (args...);
350327 } catch (...) {
351- -- m_finalizer_array.m_tail ;
328+ m_finalizer_array.pop () ;
352329 undo_allocate (sizeof (T));
353330 throw ;
354331 }
0 commit comments