diff --git a/.github/depends/zlib.sh b/.github/depends/zlib.sh index ea513a918..c69881481 100755 --- a/.github/depends/zlib.sh +++ b/.github/depends/zlib.sh @@ -27,6 +27,7 @@ while getopts "b:t:p:" c; do done mkdir $prefix || exit 1 + wget https://zlib.net/zlib-1.3.1.tar.gz || exit 1 tar -xf zlib-1.3.1.tar.gz || exit 1 cd zlib-1.3.1 diff --git a/appveyor.yml b/appveyor.yml index bcd23d817..2e71a4f71 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,9 +23,11 @@ environment: boost_subdir: lib32-msvc-14.0 build_script: - ps: | + appveyor DownloadFile http://zlib.net/zlib-1.3.1.tar.gz -FileName zlib-1.3.1.tar.gz 7z x zlib-1.3.1.tar.gz 2> $null 7z x zlib-1.3.1.tar 2> $null + cd zlib-1.3.1 md build diff --git a/erb/v1/cpp03_zone.hpp.erb b/erb/v1/cpp03_zone.hpp.erb index 6b3a57d3e..5321be7ce 100644 --- a/erb/v1/cpp03_zone.hpp.erb +++ b/erb/v1/cpp03_zone.hpp.erb @@ -29,121 +29,101 @@ MSGPACK_API_VERSION_NAMESPACE(v1) { class zone { struct finalizer { - finalizer(void (*func)(void*), void* data):m_func(func), m_data(data) {} + finalizer(void (*func)(void*), void* data, finalizer* next): m_func(func), m_data(data), m_next(next) {} void operator()() { m_func(m_data); } void (*m_func)(void*); void* m_data; + finalizer* m_next; }; + struct finalizer_array { - finalizer_array():m_tail(MSGPACK_NULLPTR), m_end(MSGPACK_NULLPTR), m_array(MSGPACK_NULLPTR) {} - void call() { - finalizer* fin = m_tail; - for(; fin != m_array; --fin) (*(fin-1))(); - } + finalizer_array(): m_head(MSGPACK_NULLPTR) {} + ~finalizer_array() { - call(); - ::free(m_array); - } - void clear() { - call(); - m_tail = m_array; + clear(); } - void push(void (*func)(void* data), void* data) - { - finalizer* fin = m_tail; - if(fin == m_end) { - push_expand(func, data); - return; + void clear() { + finalizer* fin = m_head; + finalizer* tmp = MSGPACK_NULLPTR; + while(fin) { + (*fin)(); + tmp = fin; + fin = fin->m_next; + delete tmp; } + m_head = MSGPACK_NULLPTR; + } - fin->m_func = func; - fin->m_data = data; - - ++m_tail; + void push(void (*func)(void* data), void* data) { + m_head = new finalizer(func, data, m_head); } - void push_expand(void (*func)(void*), void* data) { - const size_t nused = static_cast(m_end - m_array); - size_t nnext; - if(nused == 0) { - nnext = (sizeof(finalizer) < 72/2) ? - 72 / sizeof(finalizer) : 8; - } else { - nnext = nused * 2; - } - finalizer* tmp = - static_cast(::realloc(m_array, sizeof(finalizer) * nnext)); - if(!tmp) { - throw std::bad_alloc(); - } - m_array = tmp; - m_end = tmp + nnext; - m_tail = tmp + nused; - new (m_tail) finalizer(func, data); - ++m_tail; + void pop() { + finalizer* n = m_head->m_next; + delete m_head; + m_head = n; } - finalizer* m_tail; - finalizer* m_end; - finalizer* m_array; + + finalizer* m_head; + private: + finalizer_array(const finalizer_array&); + finalizer_array& operator=(const finalizer_array&); }; + struct chunk { chunk* m_next; }; - struct chunk_list { - chunk_list(size_t chunk_size) - { - chunk* c = static_cast(::malloc(sizeof(chunk) + chunk_size)); - if(!c) { - throw std::bad_alloc(); - } - m_head = c; - m_free = chunk_size; - m_ptr = reinterpret_cast(c) + sizeof(chunk); - c->m_next = MSGPACK_NULLPTR; - } - ~chunk_list() - { + struct chunk_list { + chunk_list(size_t chunk_size, char* ptr): m_free(chunk_size), m_ptr(ptr), m_head(MSGPACK_NULLPTR) {} + ~chunk_list() { chunk* c = m_head; while(c) { chunk* n = c->m_next; ::free(c); c = n; } + m_head = MSGPACK_NULLPTR; } - void clear(size_t chunk_size) - { + + void clear(size_t chunk_size, char* ptr) { chunk* c = m_head; - while(true) { + while(c) { chunk* n = c->m_next; - if(n) { - ::free(c); - c = n; - } else { - m_head = c; - break; - } + ::free(c); + c = n; } - m_head->m_next = MSGPACK_NULLPTR; + m_head = MSGPACK_NULLPTR; m_free = chunk_size; - m_ptr = reinterpret_cast(m_head) + sizeof(chunk); + m_ptr = ptr; } + size_t m_free; char* m_ptr; chunk* m_head; + + private: + chunk_list(const chunk_list&); + chunk_list& operator=(const chunk_list&); }; + size_t m_chunk_size; - chunk_list m_chunk_list; + chunk_list* m_chunk_list; finalizer_array m_finalizer_array; public: zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE); + ~zone(); -public: void* allocate_align(size_t size, size_t align = MSGPACK_ZONE_ALIGN); + void* allocate_no_align(size_t size); + bool allocated() { + return m_chunk_list != MSGPACK_NULLPTR; + } + void push_finalizer(void (*func)(void*), void* data); template @@ -152,24 +132,23 @@ public: void clear(); void swap(zone& o); - static void* operator new(std::size_t size) - { + + static void* operator new(std::size_t size) { void* p = ::malloc(size); if (!p) throw std::bad_alloc(); return p; } - static void operator delete(void *p) /* throw() */ - { + + static void operator delete(void *p) /* throw() */ { ::free(p); } - static void* operator new(std::size_t size, void* place) /* throw() */ - { - return ::operator new(size, place); - } - static void operator delete(void* p, void* place) /* throw() */ - { - ::operator delete(p, place); + + static void* operator new(std::size_t /*size*/, void* mem) /* throw() */ { + return mem; } + + static void operator delete(void * /*p*/, void* /*mem*/) /* throw() */ {} + /// @cond <%0.upto(GENERATION_LIMIT) {|i|%> template , typename A<%=j%><%}%>> @@ -188,18 +167,26 @@ private: static char* get_aligned(char* ptr, size_t align); + chunk_list& get_chank_lst(); + char* allocate_expand(size_t size); private: zone(const zone&); zone& operator=(const zone&); }; -inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(m_chunk_size) -{ +inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(MSGPACK_NULLPTR) {} + +inline zone::~zone() { + m_finalizer_array.~finalizer_array(); + if(m_chunk_list) { + m_chunk_list->~chunk_list(); + ::free(m_chunk_list); + m_chunk_list = MSGPACK_NULLPTR; + } } -inline char* zone::get_aligned(char* ptr, size_t align) -{ +inline char* zone::get_aligned(char* ptr, size_t align) { MSGPACK_ASSERT(align != 0 && (align & (align - 1)) == 0); // align must be 2^n (n >= 0) return reinterpret_cast( @@ -207,37 +194,45 @@ inline char* zone::get_aligned(char* ptr, size_t align) ); } -inline void* zone::allocate_align(size_t size, size_t align) -{ - char* aligned = get_aligned(m_chunk_list.m_ptr, align); - size_t adjusted_size = size + static_cast(aligned - m_chunk_list.m_ptr); - if (m_chunk_list.m_free < adjusted_size) { +inline zone::chunk_list& zone::get_chank_lst() { + if (!m_chunk_list) { + void* ptr = ::malloc(sizeof(chunk_list) + m_chunk_size); + if (!ptr) + throw std::bad_alloc(); + m_chunk_list = new (ptr) chunk_list(m_chunk_size, reinterpret_cast(ptr) + sizeof(chunk_list)); + } + return *m_chunk_list; +} + +inline void* zone::allocate_align(size_t size, size_t align) { + chunk_list& chank_lst = get_chank_lst(); + char* aligned = get_aligned(chank_lst.m_ptr, align); + size_t adjusted_size = size + static_cast(aligned - chank_lst.m_ptr); + if (chank_lst.m_free < adjusted_size) { size_t enough_size = size + align - 1; char* ptr = allocate_expand(enough_size); aligned = get_aligned(ptr, align); - adjusted_size = size + static_cast(aligned - m_chunk_list.m_ptr); + adjusted_size = size + static_cast(aligned - chank_lst.m_ptr); } - m_chunk_list.m_free -= adjusted_size; - m_chunk_list.m_ptr += adjusted_size; + chank_lst.m_free -= adjusted_size; + chank_lst.m_ptr += adjusted_size; return aligned; } -inline void* zone::allocate_no_align(size_t size) -{ - char* ptr = m_chunk_list.m_ptr; - if(m_chunk_list.m_free < size) { +inline void* zone::allocate_no_align(size_t size) { + chunk_list& chank_lst = get_chank_lst(); + char* ptr = chank_lst.m_ptr; + if(chank_lst.m_free < size) { ptr = allocate_expand(size); } - m_chunk_list.m_free -= size; - m_chunk_list.m_ptr += size; + chank_lst.m_free -= size; + chank_lst.m_ptr += size; return ptr; } -inline char* zone::allocate_expand(size_t size) -{ - chunk_list* const cl = &m_chunk_list; - +inline char* zone::allocate_expand(size_t size) { + chunk_list& cl = get_chank_lst(); size_t sz = m_chunk_size; while(sz < size) { @@ -254,60 +249,54 @@ inline char* zone::allocate_expand(size_t size) char* ptr = reinterpret_cast(c) + sizeof(chunk); - c->m_next = cl->m_head; - cl->m_head = c; - cl->m_free = sz; - cl->m_ptr = ptr; + c->m_next = cl.m_head; + cl.m_head = c; + cl.m_free = sz; + cl.m_ptr = ptr; return ptr; } -inline void zone::push_finalizer(void (*func)(void*), void* data) -{ +inline void zone::push_finalizer(void (*func)(void*), void* data) { m_finalizer_array.push(func, data); } template -inline void zone::push_finalizer(msgpack::unique_ptr obj) -{ +inline void zone::push_finalizer(msgpack::unique_ptr obj) { m_finalizer_array.push(&zone::object_delete, obj.release()); } -inline void zone::clear() -{ +inline void zone::clear() { m_finalizer_array.clear(); - m_chunk_list.clear(m_chunk_size); + if (m_chunk_list) { + m_chunk_list->clear(m_chunk_size, reinterpret_cast(m_chunk_list) + sizeof(chunk_list)); + } } -inline void zone::swap(zone& o) -{ +inline void zone::swap(zone& o) { using std::swap; swap(m_chunk_size, o.m_chunk_size); swap(m_chunk_list, o.m_chunk_list); - swap(m_finalizer_array, o.m_finalizer_array); + swap(m_finalizer_array.m_head, o.m_finalizer_array.m_head); } template -void zone::object_destruct(void* obj) -{ - static_cast(obj)->~T(); +void zone::object_delete(void* obj) { + delete static_cast(obj); } template -void zone::object_delete(void* obj) -{ - delete static_cast(obj); +void zone::object_destruct(void* obj) { + static_cast(obj)->~T(); } -inline void zone::undo_allocate(size_t size) -{ - m_chunk_list.m_ptr -= size; - m_chunk_list.m_free += size; +inline void zone::undo_allocate(size_t size) { + chunk_list& cl = get_chank_lst(); + cl.m_ptr -= size; + cl.m_free += size; } -inline std::size_t aligned_size( - std::size_t size, - std::size_t align) { +inline std::size_t aligned_size(std::size_t size, std::size_t align) { return (size + align - 1) / align * align; } @@ -326,7 +315,7 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>) try { return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } diff --git a/include/msgpack/v1/detail/cpp03_zone.hpp b/include/msgpack/v1/detail/cpp03_zone.hpp index 62def9899..c70a63ad8 100644 --- a/include/msgpack/v1/detail/cpp03_zone.hpp +++ b/include/msgpack/v1/detail/cpp03_zone.hpp @@ -29,121 +29,101 @@ MSGPACK_API_VERSION_NAMESPACE(v1) { class zone { struct finalizer { - finalizer(void (*func)(void*), void* data):m_func(func), m_data(data) {} + finalizer(void (*func)(void*), void* data, finalizer* next): m_func(func), m_data(data), m_next(next) {} void operator()() { m_func(m_data); } void (*m_func)(void*); void* m_data; + finalizer* m_next; }; + struct finalizer_array { - finalizer_array():m_tail(MSGPACK_NULLPTR), m_end(MSGPACK_NULLPTR), m_array(MSGPACK_NULLPTR) {} - void call() { - finalizer* fin = m_tail; - for(; fin != m_array; --fin) (*(fin-1))(); - } + finalizer_array(): m_head(MSGPACK_NULLPTR) {} + ~finalizer_array() { - call(); - ::free(m_array); - } - void clear() { - call(); - m_tail = m_array; + clear(); } - void push(void (*func)(void* data), void* data) - { - finalizer* fin = m_tail; - if(fin == m_end) { - push_expand(func, data); - return; + void clear() { + finalizer* fin = m_head; + finalizer* tmp = MSGPACK_NULLPTR; + while(fin) { + (*fin)(); + tmp = fin; + fin = fin->m_next; + delete tmp; } + m_head = MSGPACK_NULLPTR; + } - fin->m_func = func; - fin->m_data = data; - - ++m_tail; + void push(void (*func)(void* data), void* data) { + m_head = new finalizer(func, data, m_head); } - void push_expand(void (*func)(void*), void* data) { - const size_t nused = static_cast(m_end - m_array); - size_t nnext; - if(nused == 0) { - nnext = (sizeof(finalizer) < 72/2) ? - 72 / sizeof(finalizer) : 8; - } else { - nnext = nused * 2; - } - finalizer* tmp = - static_cast(::realloc(m_array, sizeof(finalizer) * nnext)); - if(!tmp) { - throw std::bad_alloc(); - } - m_array = tmp; - m_end = tmp + nnext; - m_tail = tmp + nused; - new (m_tail) finalizer(func, data); - ++m_tail; + void pop() { + finalizer* n = m_head->m_next; + delete m_head; + m_head = n; } - finalizer* m_tail; - finalizer* m_end; - finalizer* m_array; + + finalizer* m_head; + private: + finalizer_array(const finalizer_array&); + finalizer_array& operator=(const finalizer_array&); }; + struct chunk { chunk* m_next; }; - struct chunk_list { - chunk_list(size_t chunk_size) - { - chunk* c = static_cast(::malloc(sizeof(chunk) + chunk_size)); - if(!c) { - throw std::bad_alloc(); - } - m_head = c; - m_free = chunk_size; - m_ptr = reinterpret_cast(c) + sizeof(chunk); - c->m_next = MSGPACK_NULLPTR; - } - ~chunk_list() - { + struct chunk_list { + chunk_list(size_t chunk_size, char* ptr): m_free(chunk_size), m_ptr(ptr), m_head(MSGPACK_NULLPTR) {} + ~chunk_list() { chunk* c = m_head; while(c) { chunk* n = c->m_next; ::free(c); c = n; } + m_head = MSGPACK_NULLPTR; } - void clear(size_t chunk_size) - { + + void clear(size_t chunk_size, char* ptr) { chunk* c = m_head; - while(true) { + while(c) { chunk* n = c->m_next; - if(n) { - ::free(c); - c = n; - } else { - m_head = c; - break; - } + ::free(c); + c = n; } - m_head->m_next = MSGPACK_NULLPTR; + m_head = MSGPACK_NULLPTR; m_free = chunk_size; - m_ptr = reinterpret_cast(m_head) + sizeof(chunk); + m_ptr = ptr; } + size_t m_free; char* m_ptr; chunk* m_head; + + private: + chunk_list(const chunk_list&); + chunk_list& operator=(const chunk_list&); }; + size_t m_chunk_size; - chunk_list m_chunk_list; + chunk_list* m_chunk_list; finalizer_array m_finalizer_array; public: zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE); + ~zone(); -public: void* allocate_align(size_t size, size_t align = MSGPACK_ZONE_ALIGN); + void* allocate_no_align(size_t size); + bool allocated() { + return m_chunk_list != MSGPACK_NULLPTR; + } + void push_finalizer(void (*func)(void*), void* data); template @@ -152,24 +132,23 @@ class zone { void clear(); void swap(zone& o); - static void* operator new(std::size_t size) - { + + static void* operator new(std::size_t size) { void* p = ::malloc(size); if (!p) throw std::bad_alloc(); return p; } - static void operator delete(void *p) /* throw() */ - { + + static void operator delete(void *p) /* throw() */ { ::free(p); } - static void* operator new(std::size_t size, void* place) /* throw() */ - { - return ::operator new(size, place); - } - static void operator delete(void* p, void* place) /* throw() */ - { - ::operator delete(p, place); + + static void* operator new(std::size_t /*size*/, void* mem) /* throw() */ { + return mem; } + + static void operator delete(void * /*p*/, void* /*mem*/) /* throw() */ {} + /// @cond template @@ -233,18 +212,26 @@ class zone { static char* get_aligned(char* ptr, size_t align); + chunk_list& get_chank_lst(); + char* allocate_expand(size_t size); private: zone(const zone&); zone& operator=(const zone&); }; -inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(m_chunk_size) -{ +inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(MSGPACK_NULLPTR) {} + +inline zone::~zone() { + m_finalizer_array.clear(); + if(m_chunk_list) { + m_chunk_list->~chunk_list(); + ::free(m_chunk_list); + m_chunk_list = MSGPACK_NULLPTR; + } } -inline char* zone::get_aligned(char* ptr, size_t align) -{ +inline char* zone::get_aligned(char* ptr, size_t align) { MSGPACK_ASSERT(align != 0 && (align & (align - 1)) == 0); // align must be 2^n (n >= 0) return reinterpret_cast( @@ -252,37 +239,45 @@ inline char* zone::get_aligned(char* ptr, size_t align) ); } -inline void* zone::allocate_align(size_t size, size_t align) -{ - char* aligned = get_aligned(m_chunk_list.m_ptr, align); - size_t adjusted_size = size + static_cast(aligned - m_chunk_list.m_ptr); - if (m_chunk_list.m_free < adjusted_size) { +inline zone::chunk_list& zone::get_chank_lst() { + if (!m_chunk_list) { + void* ptr = ::malloc(sizeof(chunk_list) + m_chunk_size); + if (!ptr) + throw std::bad_alloc(); + m_chunk_list = new (ptr) chunk_list(m_chunk_size, reinterpret_cast(ptr) + sizeof(chunk_list)); + } + return *m_chunk_list; +} + +inline void* zone::allocate_align(size_t size, size_t align) { + chunk_list& chank_lst = get_chank_lst(); + char* aligned = get_aligned(chank_lst.m_ptr, align); + size_t adjusted_size = size + static_cast(aligned - chank_lst.m_ptr); + if (chank_lst.m_free < adjusted_size) { size_t enough_size = size + align - 1; char* ptr = allocate_expand(enough_size); aligned = get_aligned(ptr, align); - adjusted_size = size + static_cast(aligned - m_chunk_list.m_ptr); + adjusted_size = size + static_cast(aligned - chank_lst.m_ptr); } - m_chunk_list.m_free -= adjusted_size; - m_chunk_list.m_ptr += adjusted_size; + chank_lst.m_free -= adjusted_size; + chank_lst.m_ptr += adjusted_size; return aligned; } -inline void* zone::allocate_no_align(size_t size) -{ - char* ptr = m_chunk_list.m_ptr; - if(m_chunk_list.m_free < size) { +inline void* zone::allocate_no_align(size_t size) { + chunk_list& chank_lst = get_chank_lst(); + char* ptr = chank_lst.m_ptr; + if(chank_lst.m_free < size) { ptr = allocate_expand(size); } - m_chunk_list.m_free -= size; - m_chunk_list.m_ptr += size; + chank_lst.m_free -= size; + chank_lst.m_ptr += size; return ptr; } -inline char* zone::allocate_expand(size_t size) -{ - chunk_list* const cl = &m_chunk_list; - +inline char* zone::allocate_expand(size_t size) { + chunk_list& cl = get_chank_lst(); size_t sz = m_chunk_size; while(sz < size) { @@ -299,60 +294,54 @@ inline char* zone::allocate_expand(size_t size) char* ptr = reinterpret_cast(c) + sizeof(chunk); - c->m_next = cl->m_head; - cl->m_head = c; - cl->m_free = sz; - cl->m_ptr = ptr; + c->m_next = cl.m_head; + cl.m_head = c; + cl.m_free = sz; + cl.m_ptr = ptr; return ptr; } -inline void zone::push_finalizer(void (*func)(void*), void* data) -{ +inline void zone::push_finalizer(void (*func)(void*), void* data) { m_finalizer_array.push(func, data); } template -inline void zone::push_finalizer(msgpack::unique_ptr obj) -{ +inline void zone::push_finalizer(msgpack::unique_ptr obj) { m_finalizer_array.push(&zone::object_delete, obj.release()); } -inline void zone::clear() -{ +inline void zone::clear() { m_finalizer_array.clear(); - m_chunk_list.clear(m_chunk_size); + if (m_chunk_list) { + m_chunk_list->clear(m_chunk_size, reinterpret_cast(m_chunk_list) + sizeof(chunk_list)); + } } -inline void zone::swap(zone& o) -{ +inline void zone::swap(zone& o) { using std::swap; swap(m_chunk_size, o.m_chunk_size); swap(m_chunk_list, o.m_chunk_list); - swap(m_finalizer_array, o.m_finalizer_array); + swap(m_finalizer_array.m_head, o.m_finalizer_array.m_head); } template -void zone::object_destruct(void* obj) -{ - static_cast(obj)->~T(); +void zone::object_delete(void* obj) { + delete static_cast(obj); } template -void zone::object_delete(void* obj) -{ - delete static_cast(obj); +void zone::object_destruct(void* obj) { + static_cast(obj)->~T(); } -inline void zone::undo_allocate(size_t size) -{ - m_chunk_list.m_ptr -= size; - m_chunk_list.m_free += size; +inline void zone::undo_allocate(size_t size) { + chunk_list& cl = get_chank_lst(); + cl.m_ptr -= size; + cl.m_free += size; } -inline std::size_t aligned_size( - std::size_t size, - std::size_t align) { +inline std::size_t aligned_size(std::size_t size, std::size_t align) { return (size + align - 1) / align * align; } @@ -371,7 +360,7 @@ T* zone::allocate() try { return new (x) T(); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -390,7 +379,7 @@ T* zone::allocate(A1 a1) try { return new (x) T(a1); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -409,7 +398,7 @@ T* zone::allocate(A1 a1, A2 a2) try { return new (x) T(a1, a2); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -428,7 +417,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3) try { return new (x) T(a1, a2, a3); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -447,7 +436,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4) try { return new (x) T(a1, a2, a3, a4); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -466,7 +455,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) try { return new (x) T(a1, a2, a3, a4, a5); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -485,7 +474,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) try { return new (x) T(a1, a2, a3, a4, a5, a6); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -504,7 +493,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) try { return new (x) T(a1, a2, a3, a4, a5, a6, a7); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -523,7 +512,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) try { return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -542,7 +531,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) try { return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -561,7 +550,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, try { return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -580,7 +569,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, try { return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -599,7 +588,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, try { return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -618,7 +607,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, try { return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -637,7 +626,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, try { return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } @@ -656,7 +645,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, try { return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } diff --git a/include/msgpack/v1/detail/cpp11_zone.hpp b/include/msgpack/v1/detail/cpp11_zone.hpp index 2586f2755..611752f00 100644 --- a/include/msgpack/v1/detail/cpp11_zone.hpp +++ b/include/msgpack/v1/detail/cpp11_zone.hpp @@ -29,154 +29,113 @@ MSGPACK_API_VERSION_NAMESPACE(v1) { class zone { private: struct finalizer { - finalizer(void (*func)(void*), void* data):m_func(func), m_data(data) {} + finalizer(void (*func)(void*), void* data, finalizer* next): m_func(func), m_data(data), m_next(next) {} void operator()() { m_func(m_data); } void (*m_func)(void*); void* m_data; + finalizer* m_next; }; + struct finalizer_array { - finalizer_array():m_tail(MSGPACK_NULLPTR), m_end(MSGPACK_NULLPTR), m_array(MSGPACK_NULLPTR) {} - void call() { - finalizer* fin = m_tail; - for(; fin != m_array; --fin) (*(fin-1))(); - } + finalizer_array(): m_head(MSGPACK_NULLPTR) {} + ~finalizer_array() { - call(); - ::free(m_array); + clear(); } - void clear() { - call(); - m_tail = m_array; - } - void push(void (*func)(void* data), void* data) - { - finalizer* fin = m_tail; - if(fin == m_end) { - push_expand(func, data); - return; + void clear() { + finalizer* fin = m_head; + finalizer* tmp = MSGPACK_NULLPTR; + while(fin) { + (*fin)(); + tmp = fin; + fin = fin->m_next; + delete tmp; } + m_head = MSGPACK_NULLPTR; + } - fin->m_func = func; - fin->m_data = data; - - ++m_tail; + void push(void (*func)(void* data), void* data) { + m_head = new finalizer(func, data, m_head); } - void push_expand(void (*func)(void*), void* data) { - const size_t nused = static_cast(m_end - m_array); - size_t nnext; - if(nused == 0) { - nnext = (sizeof(finalizer) < 72/2) ? - 72 / sizeof(finalizer) : 8; - } else { - nnext = nused * 2; - } - finalizer* tmp = - static_cast(::realloc(m_array, sizeof(finalizer) * nnext)); - if(!tmp) { - throw std::bad_alloc(); - } - m_array = tmp; - m_end = tmp + nnext; - m_tail = tmp + nused; - new (m_tail) finalizer(func, data); - ++m_tail; + void pop() { + auto n = m_head->m_next; + delete m_head; + m_head = n; } - finalizer_array(finalizer_array&& other) noexcept - :m_tail(other.m_tail), m_end(other.m_end), m_array(other.m_array) - { - other.m_tail = MSGPACK_NULLPTR; - other.m_end = MSGPACK_NULLPTR; - other.m_array = MSGPACK_NULLPTR; + + finalizer_array(finalizer_array&& other) noexcept: m_head(other.m_head) { + other.m_head = MSGPACK_NULLPTR; } - finalizer_array& operator=(finalizer_array&& other) noexcept - { - this->~finalizer_array(); - new (this) finalizer_array(std::move(other)); + + finalizer_array& operator=(finalizer_array&& other) noexcept { + m_head = other.m_head; + other.m_head = MSGPACK_NULLPTR; return *this; } - finalizer* m_tail; - finalizer* m_end; - finalizer* m_array; - private: + finalizer* m_head; finalizer_array(const finalizer_array&); finalizer_array& operator=(const finalizer_array&); }; + struct chunk { chunk* m_next; }; - struct chunk_list { - chunk_list(size_t chunk_size) - { - chunk* c = static_cast(::malloc(sizeof(chunk) + chunk_size)); - if(!c) { - throw std::bad_alloc(); - } - m_head = c; - m_free = chunk_size; - m_ptr = reinterpret_cast(c) + sizeof(chunk); - c->m_next = MSGPACK_NULLPTR; - } - ~chunk_list() - { + struct chunk_list { + chunk_list(size_t chunk_size, char* ptr): m_free(chunk_size), m_ptr(ptr), m_head(MSGPACK_NULLPTR) {} + ~chunk_list() { chunk* c = m_head; while(c) { chunk* n = c->m_next; ::free(c); c = n; } + m_head = MSGPACK_NULLPTR; } - void clear(size_t chunk_size) - { + + void clear(size_t chunk_size, char* ptr) { chunk* c = m_head; - while(true) { + while(c) { chunk* n = c->m_next; - if(n) { - ::free(c); - c = n; - } else { - m_head = c; - break; - } + ::free(c); + c = n; } - m_head->m_next = MSGPACK_NULLPTR; + m_head = MSGPACK_NULLPTR; m_free = chunk_size; - m_ptr = reinterpret_cast(m_head) + sizeof(chunk); - } - chunk_list(chunk_list&& other) noexcept - :m_free(other.m_free), m_ptr(other.m_ptr), m_head(other.m_head) - { - other.m_head = MSGPACK_NULLPTR; - } - chunk_list& operator=(chunk_list&& other) noexcept - { - this->~chunk_list(); - new (this) chunk_list(std::move(other)); - return *this; + m_ptr = ptr; } size_t m_free; char* m_ptr; chunk* m_head; + private: + chunk_list(chunk_list&& other) noexcept = delete; + chunk_list& operator=(chunk_list&& other) noexcept = delete; chunk_list(const chunk_list&); chunk_list& operator=(const chunk_list&); }; + size_t m_chunk_size; - chunk_list m_chunk_list; + chunk_list* m_chunk_list{}; finalizer_array m_finalizer_array; public: zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE); + ~zone(); -public: void* allocate_align(size_t size, size_t align = MSGPACK_ZONE_ALIGN); + void* allocate_no_align(size_t size); + bool allocated() { + return m_chunk_list != MSGPACK_NULLPTR; + } + void push_finalizer(void (*func)(void*), void* data); template @@ -186,23 +145,21 @@ class zone { void swap(zone& o); - static void* operator new(std::size_t size) - { + static void* operator new(std::size_t size) { void* p = ::malloc(size); if (!p) throw std::bad_alloc(); return p; } - static void operator delete(void *p) noexcept - { + + static void operator delete(void *p) noexcept { ::free(p); } - static void* operator new(std::size_t /*size*/, void* mem) noexcept - { + + static void* operator new(std::size_t /*size*/, void* mem) noexcept { return mem; } - static void operator delete(void * /*p*/, void* /*mem*/) noexcept - { - } + + static void operator delete(void * /*p*/, void* /*mem*/) noexcept {} template T* allocate(Args... args); @@ -223,15 +180,23 @@ class zone { static char* get_aligned(char* ptr, size_t align); + chunk_list& get_chank_lst(); + char* allocate_expand(size_t size); }; -inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(m_chunk_size) -{ +inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(MSGPACK_NULLPTR) {} + +inline zone::~zone() { + m_finalizer_array.clear(); + if(m_chunk_list) { + m_chunk_list->~chunk_list(); + ::free(m_chunk_list); + m_chunk_list = MSGPACK_NULLPTR; + } } -inline char* zone::get_aligned(char* ptr, size_t align) -{ +inline char* zone::get_aligned(char* ptr, size_t align) { MSGPACK_ASSERT(align != 0 && (align & (align - 1)) == 0); // align must be 2^n (n >= 0) return reinterpret_cast( @@ -239,37 +204,45 @@ inline char* zone::get_aligned(char* ptr, size_t align) ); } -inline void* zone::allocate_align(size_t size, size_t align) -{ - char* aligned = get_aligned(m_chunk_list.m_ptr, align); - size_t adjusted_size = size + static_cast(aligned - m_chunk_list.m_ptr); - if (m_chunk_list.m_free < adjusted_size) { +inline zone::chunk_list& zone::get_chank_lst() { + if (!m_chunk_list) { + auto ptr = ::malloc(sizeof(chunk_list) + m_chunk_size); + if (!ptr) + throw std::bad_alloc(); + m_chunk_list = new (ptr) chunk_list(m_chunk_size, reinterpret_cast(ptr) + sizeof(chunk_list)); + } + return *m_chunk_list; +} + +inline void* zone::allocate_align(size_t size, size_t align) { + chunk_list& chank_lst = get_chank_lst(); + char* aligned = get_aligned(chank_lst.m_ptr, align); + size_t adjusted_size = size + static_cast(aligned - chank_lst.m_ptr); + if (chank_lst.m_free < adjusted_size) { size_t enough_size = size + align - 1; char* ptr = allocate_expand(enough_size); aligned = get_aligned(ptr, align); - adjusted_size = size + static_cast(aligned - m_chunk_list.m_ptr); + adjusted_size = size + static_cast(aligned - chank_lst.m_ptr); } - m_chunk_list.m_free -= adjusted_size; - m_chunk_list.m_ptr += adjusted_size; + chank_lst.m_free -= adjusted_size; + chank_lst.m_ptr += adjusted_size; return aligned; } -inline void* zone::allocate_no_align(size_t size) -{ - char* ptr = m_chunk_list.m_ptr; - if(m_chunk_list.m_free < size) { +inline void* zone::allocate_no_align(size_t size) { + chunk_list& chank_lst = get_chank_lst(); + char* ptr = chank_lst.m_ptr; + if(chank_lst.m_free < size) { ptr = allocate_expand(size); } - m_chunk_list.m_free -= size; - m_chunk_list.m_ptr += size; + chank_lst.m_free -= size; + chank_lst.m_ptr += size; return ptr; } -inline char* zone::allocate_expand(size_t size) -{ - chunk_list* const cl = &m_chunk_list; - +inline char* zone::allocate_expand(size_t size) { + chunk_list& cl = get_chank_lst(); size_t sz = m_chunk_size; while(sz < size) { @@ -286,58 +259,56 @@ inline char* zone::allocate_expand(size_t size) char* ptr = reinterpret_cast(c) + sizeof(chunk); - c->m_next = cl->m_head; - cl->m_head = c; - cl->m_free = sz; - cl->m_ptr = ptr; + c->m_next = cl.m_head; + cl.m_head = c; + cl.m_free = sz; + cl.m_ptr = ptr; return ptr; } -inline void zone::push_finalizer(void (*func)(void*), void* data) -{ +inline void zone::push_finalizer(void (*func)(void*), void* data) { m_finalizer_array.push(func, data); } template -inline void zone::push_finalizer(msgpack::unique_ptr obj) -{ +inline void zone::push_finalizer(msgpack::unique_ptr obj) { m_finalizer_array.push(&zone::object_delete, obj.release()); } -inline void zone::clear() -{ +inline void zone::clear() { m_finalizer_array.clear(); - m_chunk_list.clear(m_chunk_size); + if (m_chunk_list) { + m_chunk_list->clear(m_chunk_size, reinterpret_cast(m_chunk_list) + sizeof(chunk_list)); + } } -inline void zone::swap(zone& o) -{ +inline void zone::swap(zone& o) { std::swap(*this, o); } template -void zone::object_delete(void* obj) -{ +void zone::object_delete(void* obj) { delete static_cast(obj); } template -void zone::object_destruct(void* obj) -{ +void zone::object_destruct(void* obj) { static_cast(obj)->~T(); } -inline void zone::undo_allocate(size_t size) -{ - m_chunk_list.m_ptr -= size; - m_chunk_list.m_free += size; +inline void zone::undo_allocate(size_t size) { + chunk_list& cl = get_chank_lst(); + cl.m_ptr -= size; + cl.m_free += size; } +inline std::size_t aligned_size(std::size_t size, std::size_t align) { + return (size + align - 1) / align * align; +} template -T* zone::allocate(Args... args) -{ +T* zone::allocate(Args... args) { void* x = allocate_align(sizeof(T), MSGPACK_ZONE_ALIGNOF(T)); try { m_finalizer_array.push(&zone::object_destruct, x); @@ -348,18 +319,12 @@ T* zone::allocate(Args... args) try { return new (x) T(args...); } catch (...) { - --m_finalizer_array.m_tail; + m_finalizer_array.pop(); undo_allocate(sizeof(T)); throw; } } -inline std::size_t aligned_size( - std::size_t size, - std::size_t align) { - return (size + align - 1) / align * align; -} - /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v1) /// @endcond diff --git a/preprocess.rb b/preprocess.rb new file mode 100644 index 000000000..95cd313bd --- /dev/null +++ b/preprocess.rb @@ -0,0 +1,17 @@ +require 'erb' + +files = { + "erb/v1/cpp03_msgpack_tuple_decl.hpp" => "include/msgpack/v1/adaptor/detail/cpp03_msgpack_tuple_decl.hpp", + "erb/v1/cpp03_msgpack_tuple.hpp" => "include/msgpack/v1/adaptor/detail/cpp03_msgpack_tuple.hpp", + "erb/v1/cpp03_define_array_decl.hpp" => "include/msgpack/v1/adaptor/detail/cpp03_define_array_decl.hpp", + "erb/v1/cpp03_define_array.hpp" => "include/msgpack/v1/adaptor/detail/cpp03_define_array.hpp", + "erb/v1/cpp03_define_map_decl.hpp" => "include/msgpack/v1/adaptor/detail/cpp03_define_map_decl.hpp", + "erb/v1/cpp03_define_map.hpp" => "include/msgpack/v1/adaptor/detail/cpp03_define_map.hpp", + "erb/v1/cpp03_zone_decl.hpp" => "include/msgpack/v1/detail/cpp03_zone_decl.hpp", + "erb/v1/cpp03_zone.hpp" => "include/msgpack/v1/detail/cpp03_zone.hpp" +} + +files.map { |erb, hpp| + res = ERB.new(File.open(erb+".erb").read).result + File.write(hpp, res) +} \ No newline at end of file