diff --git a/erb/cpp03_zone.hpp.erb b/erb/cpp03_zone.hpp.erb index c64273ad..f8f96cf1 100644 --- a/erb/cpp03_zone.hpp.erb +++ b/erb/cpp03_zone.hpp.erb @@ -150,7 +150,7 @@ public: zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE) /* throw() */; public: - void* allocate_align(size_t size); + 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); @@ -203,10 +203,21 @@ inline zone::zone(size_t chunk_size) /* throw() */ :m_chunk_size(chunk_size), m_ { } -inline void* zone::allocate_align(size_t size) +inline void* zone::allocate_align(size_t size, size_t align) { - return allocate_no_align( - ((size)+((MSGPACK_ZONE_ALIGN)-1)) & ~((MSGPACK_ZONE_ALIGN)-1)); + 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) diff --git a/include/msgpack/detail/cpp03_zone.hpp b/include/msgpack/detail/cpp03_zone.hpp index adc8e78e..880544c1 100644 --- a/include/msgpack/detail/cpp03_zone.hpp +++ b/include/msgpack/detail/cpp03_zone.hpp @@ -150,7 +150,7 @@ public: zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE) /* throw() */; public: - void* allocate_align(size_t size); + 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); @@ -248,10 +248,21 @@ inline zone::zone(size_t chunk_size) /* throw() */ :m_chunk_size(chunk_size), m_ { } -inline void* zone::allocate_align(size_t size) +inline void* zone::allocate_align(size_t size, size_t align) { - return allocate_no_align( - ((size)+((MSGPACK_ZONE_ALIGN)-1)) & ~((MSGPACK_ZONE_ALIGN)-1)); + 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) diff --git a/include/msgpack/detail/cpp11_zone.hpp b/include/msgpack/detail/cpp11_zone.hpp index 4211466f..e18a6cdc 100644 --- a/include/msgpack/detail/cpp11_zone.hpp +++ b/include/msgpack/detail/cpp11_zone.hpp @@ -188,7 +188,7 @@ public: zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE) noexcept; public: - void* allocate_align(size_t size); + 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); @@ -243,10 +243,21 @@ inline zone::zone(size_t chunk_size) noexcept:m_chunk_size(chunk_size), m_chunk_ { } -inline void* zone::allocate_align(size_t size) +inline void* zone::allocate_align(size_t size, size_t align) { - return allocate_no_align( - ((size)+((MSGPACK_ZONE_ALIGN)-1)) & ~((MSGPACK_ZONE_ALIGN)-1)); + 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) diff --git a/include/msgpack/zone.h b/include/msgpack/zone.h index 05e6bc8d..572185ce 100644 --- a/include/msgpack/zone.h +++ b/include/msgpack/zone.h @@ -113,8 +113,25 @@ void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size) static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size) { - return msgpack_zone_malloc_no_align(zone, - ((size)+((MSGPACK_ZONE_ALIGN)-1)) & ~((MSGPACK_ZONE_ALIGN)-1)); + char* aligned = + (char*)( + (size_t)( + zone->chunk_list.ptr + (MSGPACK_ZONE_ALIGN - 1) + ) / MSGPACK_ZONE_ALIGN * MSGPACK_ZONE_ALIGN + ); + size_t adjusted_size = size + (aligned - zone->chunk_list.ptr); + if(zone->chunk_list.free >= adjusted_size) { + zone->chunk_list.free -= adjusted_size; + zone->chunk_list.ptr += adjusted_size; + return aligned; + } + { + void* ptr = msgpack_zone_malloc_expand(zone, size + (MSGPACK_ZONE_ALIGN - 1)); + if (ptr) { + return (char*)((size_t)(ptr) / MSGPACK_ZONE_ALIGN * MSGPACK_ZONE_ALIGN); + } + } + return NULL; } @@ -152,4 +169,3 @@ static inline void msgpack_zone_swap(msgpack_zone* a, msgpack_zone* b) #endif #endif /* msgpack/zone.h */ - diff --git a/test/zone.cpp b/test/zone.cpp index b2dc543e..6e69828c 100644 --- a/test/zone.cpp +++ b/test/zone.cpp @@ -4,12 +4,28 @@ TEST(zone, allocate_align) { msgpack::zone z; - char* buf1 = (char*)z.allocate_align(4); - memcpy(buf1, "test", 4); - char* buf2 = (char*)z.allocate_align(4); - memcpy(buf2, "test", 4); + char* start = (char*)z.allocate_align(1); + EXPECT_EQ(reinterpret_cast(start) % sizeof(int), 0); + for (std::size_t s = 1; s < sizeof(int); ++s) { + z.allocate_no_align(s); + char* buf_a = (char*)z.allocate_align(1); + EXPECT_EQ(0, reinterpret_cast(buf_a) % sizeof(int)); + } } +TEST(zone, allocate_align_custom) +{ + msgpack::zone z; + for (std::size_t align = 1; align < 64; ++align) { + char* start = (char*)z.allocate_align(1, align); + EXPECT_EQ(reinterpret_cast(start) % align, 0); + for (std::size_t s = 1; s < align; ++s) { + (char*)z.allocate_no_align(s); + char* buf_a = (char*)z.allocate_align(1, align); + EXPECT_EQ(0, reinterpret_cast(buf_a) % align); + } + } +} class myclass { public: @@ -75,4 +91,3 @@ TEST(zone, allocate_no_align) char* buf2 = (char*)z.allocate_no_align(4); EXPECT_EQ(buf1+4, buf2); } -