From 53795c74aead4e6021bc788b788f8ed5b4a0166d Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Mon, 3 Apr 2017 18:49:58 -0700 Subject: uhd: add cut-down rpclib source tree and import tool --- .../include/rpc/msgpack/detail/cpp03_zone.hpp | 676 +++++++++++++++++++++ .../include/rpc/msgpack/detail/cpp11_zone.hpp | 376 ++++++++++++ 2 files changed, 1052 insertions(+) create mode 100644 host/lib/deps/rpclib/include/rpc/msgpack/detail/cpp03_zone.hpp create mode 100644 host/lib/deps/rpclib/include/rpc/msgpack/detail/cpp11_zone.hpp (limited to 'host/lib/deps/rpclib/include/rpc/msgpack/detail') diff --git a/host/lib/deps/rpclib/include/rpc/msgpack/detail/cpp03_zone.hpp b/host/lib/deps/rpclib/include/rpc/msgpack/detail/cpp03_zone.hpp new file mode 100644 index 000000000..5c7703070 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/msgpack/detail/cpp03_zone.hpp @@ -0,0 +1,676 @@ +// +// MessagePack for C++ memory pool +// +// Copyright (C) 2008-2010 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_CPP03_ZONE_HPP +#define MSGPACK_CPP03_ZONE_HPP + +#include +#include +#include + +#include "rpc/msgpack/versioning.hpp" + +#ifndef MSGPACK_ZONE_CHUNK_SIZE +#define MSGPACK_ZONE_CHUNK_SIZE 8192 +#endif + +#ifndef MSGPACK_ZONE_ALIGN +#define MSGPACK_ZONE_ALIGN sizeof(void*) +#endif + + +namespace clmdep_msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +class zone { + struct finalizer { + finalizer(void (*func)(void*), void* data):m_func(func), m_data(data) {} + void operator()() { m_func(m_data); } + void (*m_func)(void*); + void* m_data; + }; + struct finalizer_array { + finalizer_array():m_tail(nullptr), m_end(nullptr), m_array(nullptr) {} + void call() { + finalizer* fin = m_tail; + for(; fin != m_array; --fin) (*(fin-1))(); + } + ~finalizer_array() { + call(); + ::free(m_array); + } + 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; + } + + fin->m_func = func; + fin->m_data = data; + + ++m_tail; + } + void push_expand(void (*func)(void*), void* data) { + const size_t nused = 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; + } + finalizer* m_tail; + finalizer* m_end; + finalizer* m_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 = nullptr; + } + ~chunk_list() + { + chunk* c = m_head; + while(c) { + chunk* n = c->m_next; + ::free(c); + c = n; + } + } + void clear(size_t chunk_size) + { + chunk* c = m_head; + while(true) { + chunk* n = c->m_next; + if(n) { + ::free(c); + c = n; + } else { + break; + } + } + m_head->m_next = nullptr; + m_free = chunk_size; + m_ptr = reinterpret_cast(m_head) + sizeof(chunk); + } + size_t m_free; + char* m_ptr; + chunk* m_head; + }; + size_t m_chunk_size; + chunk_list m_chunk_list; + finalizer_array m_finalizer_array; + +public: + zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE) /* throw() */; + +public: + void* allocate_align(size_t size, size_t align = MSGPACK_ZONE_ALIGN); + void* allocate_no_align(size_t size); + + void push_finalizer(void (*func)(void*), void* data); + + template + void push_finalizer(clmdep_msgpack::unique_ptr obj); + + void clear(); + + void swap(zone& o); + 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() */ + { + ::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); + } + /// @cond + + template + T* allocate(); + + template + T* allocate(A1 a1); + + template + T* allocate(A1 a1, A2 a2); + + template + T* allocate(A1 a1, A2 a2, A3 a3); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14); + + template + T* allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15); + + /// @endcond + +private: + void undo_allocate(size_t size); + + template + static void object_destruct(void* obj); + + template + static void object_delete(void* obj); + + void* allocate_expand(size_t size); +private: + zone(const zone&); + zone& operator=(const zone&); +}; + +inline zone::zone(size_t chunk_size) /* throw() */ :m_chunk_size(chunk_size), m_chunk_list(m_chunk_size) +{ +} + +inline void* zone::allocate_align(size_t size, size_t align) +{ + char* aligned = + reinterpret_cast( + reinterpret_cast( + (m_chunk_list.m_ptr + (align - 1))) / align * align); + size_t adjusted_size = size + (aligned - m_chunk_list.m_ptr); + if(m_chunk_list.m_free >= adjusted_size) { + m_chunk_list.m_free -= adjusted_size; + m_chunk_list.m_ptr += adjusted_size; + return aligned; + } + return reinterpret_cast( + reinterpret_cast( + allocate_expand(size + (align - 1))) / align * align); +} + +inline void* zone::allocate_no_align(size_t size) +{ + if(m_chunk_list.m_free < size) { + return allocate_expand(size); + } + + char* ptr = m_chunk_list.m_ptr; + m_chunk_list.m_free -= size; + m_chunk_list.m_ptr += size; + + return ptr; +} + +inline void* zone::allocate_expand(size_t size) +{ + chunk_list* const cl = &m_chunk_list; + + size_t sz = m_chunk_size; + + while(sz < size) { + size_t tmp_sz = sz * 2; + if (tmp_sz <= sz) { + sz = size; + break; + } + sz = tmp_sz; + } + + chunk* c = static_cast(::malloc(sizeof(chunk) + sz)); + if (!c) throw std::bad_alloc(); + + char* ptr = reinterpret_cast(c) + sizeof(chunk); + + c->m_next = cl->m_head; + cl->m_head = c; + cl->m_free = sz - size; + cl->m_ptr = ptr + size; + + return ptr; +} + +inline void zone::push_finalizer(void (*func)(void*), void* data) +{ + m_finalizer_array.push(func, data); +} + +template +inline void zone::push_finalizer(clmdep_msgpack::unique_ptr obj) +{ + m_finalizer_array.push(&zone::object_delete, obj.release()); +} + +inline void zone::clear() +{ + m_finalizer_array.clear(); + m_chunk_list.clear(m_chunk_size); +} + +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); +} + +template +void zone::object_destruct(void* obj) +{ + static_cast(obj)->~T(); +} + +template +void zone::object_delete(void* obj) +{ + delete static_cast(obj); +} + +inline void zone::undo_allocate(size_t size) +{ + m_chunk_list.m_ptr -= size; + m_chunk_list.m_free += size; +} + +inline std::size_t aligned_size( + std::size_t size, + std::size_t align = MSGPACK_ZONE_ALIGN) { + return (size + align - 1) / align * align; +} + +/// @cond + +template +T* zone::allocate() +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3, a4); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3, a4, a5); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3, a4, a5, a6); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3, a4, a5, a6, a7); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + 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; + undo_allocate(sizeof(T)); + throw; + } +} + +template +T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + 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; + undo_allocate(sizeof(T)); + throw; + } +} + +/// @endcond + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace clmdep_msgpack + +#endif // MSGPACK_CPP03_ZONE_HPP diff --git a/host/lib/deps/rpclib/include/rpc/msgpack/detail/cpp11_zone.hpp b/host/lib/deps/rpclib/include/rpc/msgpack/detail/cpp11_zone.hpp new file mode 100644 index 000000000..2c4e82ca1 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/msgpack/detail/cpp11_zone.hpp @@ -0,0 +1,376 @@ +// +// MessagePack for C++ memory pool +// +// Copyright (C) 2008-2013 FURUHASHI Sadayuki and KONDO Takatoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_CPP11_ZONE_HPP +#define MSGPACK_CPP11_ZONE_HPP + +#include "rpc/msgpack/versioning.hpp" + +#include +#include +#include + +#include "rpc/msgpack/cpp_config.hpp" + +#ifndef MSGPACK_ZONE_CHUNK_SIZE +#define MSGPACK_ZONE_CHUNK_SIZE 8192 +#endif + +#ifndef MSGPACK_ZONE_ALIGN +#define MSGPACK_ZONE_ALIGN sizeof(void*) +#endif + +namespace clmdep_msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +class zone { +private: + struct finalizer { + finalizer(void (*func)(void*), void* data):m_func(func), m_data(data) {} + void operator()() { m_func(m_data); } + void (*m_func)(void*); + void* m_data; + }; + struct finalizer_array { + finalizer_array():m_tail(nullptr), m_end(nullptr), m_array(nullptr) {} + void call() { + finalizer* fin = m_tail; + for(; fin != m_array; --fin) (*(fin-1))(); + } + ~finalizer_array() { + call(); + ::free(m_array); + } + 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; + } + + fin->m_func = func; + fin->m_data = data; + + ++m_tail; + } + void push_expand(void (*func)(void*), void* data) { + const size_t nused = 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; + } + finalizer_array(finalizer_array&& other) noexcept + :m_tail(other.m_tail), m_end(other.m_end), m_array(other.m_array) + { + other.m_tail = nullptr; + other.m_end = nullptr; + other.m_array = nullptr; + } + finalizer_array& operator=(finalizer_array&& other) noexcept + { + this->~finalizer_array(); + new (this) finalizer_array(std::move(other)); + return *this; + } + + finalizer* m_tail; + finalizer* m_end; + finalizer* m_array; + + 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 = nullptr; + } + ~chunk_list() + { + chunk* c = m_head; + while(c) { + chunk* n = c->m_next; + ::free(c); + c = n; + } + } + void clear(size_t chunk_size) + { + chunk* c = m_head; + while(true) { + chunk* n = c->m_next; + if(n) { + ::free(c); + c = n; + } else { + m_head = c; + break; + } + } + m_head->m_next = 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 = nullptr; + } + chunk_list& operator=(chunk_list&& other) noexcept + { + this->~chunk_list(); + new (this) chunk_list(std::move(other)); + return *this; + } + + 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; + finalizer_array m_finalizer_array; + +public: + zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE) noexcept; + +public: + void* allocate_align(size_t size, size_t align = MSGPACK_ZONE_ALIGN); + void* allocate_no_align(size_t size); + + void push_finalizer(void (*func)(void*), void* data); + + template + void push_finalizer(clmdep_msgpack::unique_ptr obj); + + void clear(); + + void swap(zone& o); + + + 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 + { + ::free(p); + } + static void* operator new(std::size_t /*size*/, void* mem) noexcept + { + return mem; + } + static void operator delete(void * /*p*/, void* /*mem*/) noexcept + { + } + + template + T* allocate(Args... args); + + zone(zone&&) = default; + zone& operator=(zone&&) = default; + zone(const zone&) = delete; + zone& operator=(const zone&) = delete; + +private: + void undo_allocate(size_t size); + + template + static void object_destruct(void* obj); + + template + static void object_delete(void* obj); + + void* allocate_expand(size_t size); +}; + +inline zone::zone(size_t chunk_size) noexcept:m_chunk_size(chunk_size), m_chunk_list(m_chunk_size) +{ +} + +inline void* zone::allocate_align(size_t size, size_t align) +{ + char* aligned = + reinterpret_cast( + reinterpret_cast( + (m_chunk_list.m_ptr + (align - 1))) / align * align); + size_t adjusted_size = size + (aligned - m_chunk_list.m_ptr); + if(m_chunk_list.m_free >= adjusted_size) { + m_chunk_list.m_free -= adjusted_size; + m_chunk_list.m_ptr += adjusted_size; + return aligned; + } + return reinterpret_cast( + reinterpret_cast( + allocate_expand(size + (align - 1))) / align * align); +} + +inline void* zone::allocate_no_align(size_t size) +{ + if(m_chunk_list.m_free < size) { + return allocate_expand(size); + } + + char* ptr = m_chunk_list.m_ptr; + m_chunk_list.m_free -= size; + m_chunk_list.m_ptr += size; + + return ptr; +} + +inline void* zone::allocate_expand(size_t size) +{ + chunk_list* const cl = &m_chunk_list; + + size_t sz = m_chunk_size; + + while(sz < size) { + size_t tmp_sz = sz * 2; + if (tmp_sz <= sz) { + sz = size; + break; + } + sz = tmp_sz; + } + + chunk* c = static_cast(::malloc(sizeof(chunk) + sz)); + if (!c) throw std::bad_alloc(); + + char* ptr = reinterpret_cast(c) + sizeof(chunk); + + c->m_next = cl->m_head; + cl->m_head = c; + cl->m_free = sz - size; + cl->m_ptr = ptr + size; + + return ptr; +} + +inline void zone::push_finalizer(void (*func)(void*), void* data) +{ + m_finalizer_array.push(func, data); +} + +template +inline void zone::push_finalizer(clmdep_msgpack::unique_ptr obj) +{ + m_finalizer_array.push(&zone::object_delete, obj.release()); +} + +inline void zone::clear() +{ + m_finalizer_array.clear(); + m_chunk_list.clear(m_chunk_size); +} + +inline void zone::swap(zone& o) +{ + std::swap(*this, o); +} + +template +void zone::object_delete(void* obj) +{ + delete static_cast(obj); +} + +template +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; +} + + +template +T* zone::allocate(Args... args) +{ + void* x = allocate_align(sizeof(T)); + try { + m_finalizer_array.push(&zone::object_destruct, x); + } catch (...) { + undo_allocate(sizeof(T)); + throw; + } + try { + return new (x) T(args...); + } catch (...) { + --m_finalizer_array.m_tail; + undo_allocate(sizeof(T)); + throw; + } +} + +inline std::size_t aligned_size( + std::size_t size, + std::size_t align = MSGPACK_ZONE_ALIGN) { + return (size + align - 1) / align * align; +} + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace clmdep_msgpack + +#endif // MSGPACK_CPP11_ZONE_HPP -- cgit v1.2.3