Removed redundant memory allocation from zone.

Removed zone::create and zone::destroy.
We can use zone as follows:
   zone z; // on stack
   zone* z = new zone; // on heap

Fixed a resource leak when zone::push_finalizer(msgpack::unique_ptr<T>) is called.
This commit is contained in:
Takatoshi Kondo
2014-08-07 15:23:34 +09:00
parent b5b459cfca
commit 17e696fc0d
5 changed files with 111 additions and 128 deletions

View File

@@ -114,14 +114,10 @@ class zone {
~chunk_list()
{
chunk* c = m_head;
while(true) {
while(c) {
chunk* n = c->m_next;
::free(c);
if(n) {
c = n;
} else {
break;
}
c = n;
}
}
void clear(size_t chunk_size)
@@ -152,8 +148,6 @@ public:
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE) /* throw() */;
public:
static zone* create(size_t chunk_size);
static void destroy(zone* zone);
void* allocate_align(size_t size);
void* allocate_no_align(size_t size);
@@ -192,28 +186,14 @@ private:
void undo_allocate(size_t size);
template <typename T>
static void object_destructor(void* obj);
static void object_destruct(void* obj);
template <typename T>
static void object_delete(void* obj);
void* allocate_expand(size_t size);
};
inline zone* zone::create(size_t chunk_size)
{
zone* z = static_cast<zone*>(::malloc(sizeof(zone) + chunk_size));
if (!z) {
throw std::bad_alloc();
}
new (z) zone(chunk_size);
return z;
}
inline void zone::destroy(zone* z)
{
z->~zone();
::free(z);
}
inline zone::zone(size_t chunk_size) /* throw() */ :m_chunk_size(chunk_size), m_chunk_list(m_chunk_size)
{
}
@@ -268,8 +248,7 @@ inline void zone::push_finalizer(void (*func)(void*), void* data)
template <typename T>
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj)
{
m_finalizer_array.push(&zone::object_destructor<T>, obj.get());
obj.release();
m_finalizer_array.push(&zone::object_delete<T>, obj.release());
}
inline void zone::clear()
@@ -284,9 +263,15 @@ inline void zone::swap(zone& o)
}
template <typename T>
void zone::object_destructor(void* obj)
void zone::object_destruct(void* obj)
{
reinterpret_cast<T*>(obj)->~T();
static_cast<T*>(obj)->~T();
}
template <typename T>
void zone::object_delete(void* obj)
{
delete static_cast<T*>(obj);
}
inline void zone::undo_allocate(size_t size)
@@ -301,7 +286,7 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
{
void* x = allocate_align(sizeof(T));
try {
m_finalizer_array.push(&zone::object_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;

View File

@@ -114,14 +114,10 @@ class zone {
~chunk_list()
{
chunk* c = m_head;
while(true) {
while(c) {
chunk* n = c->m_next;
::free(c);
if(n) {
c = n;
} else {
break;
}
c = n;
}
}
void clear(size_t chunk_size)
@@ -152,8 +148,6 @@ public:
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE) /* throw() */;
public:
static zone* create(size_t chunk_size);
static void destroy(zone* zone);
void* allocate_align(size_t size);
void* allocate_no_align(size_t size);
@@ -237,28 +231,14 @@ private:
void undo_allocate(size_t size);
template <typename T>
static void object_destructor(void* obj);
static void object_destruct(void* obj);
template <typename T>
static void object_delete(void* obj);
void* allocate_expand(size_t size);
};
inline zone* zone::create(size_t chunk_size)
{
zone* z = static_cast<zone*>(::malloc(sizeof(zone) + chunk_size));
if (!z) {
throw std::bad_alloc();
}
new (z) zone(chunk_size);
return z;
}
inline void zone::destroy(zone* z)
{
z->~zone();
::free(z);
}
inline zone::zone(size_t chunk_size) /* throw() */ :m_chunk_size(chunk_size), m_chunk_list(m_chunk_size)
{
}
@@ -313,8 +293,7 @@ inline void zone::push_finalizer(void (*func)(void*), void* data)
template <typename T>
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj)
{
m_finalizer_array.push(&zone::object_destructor<T>, obj.get());
obj.release();
m_finalizer_array.push(&zone::object_delete<T>, obj.release());
}
inline void zone::clear()
@@ -329,9 +308,15 @@ inline void zone::swap(zone& o)
}
template <typename T>
void zone::object_destructor(void* obj)
void zone::object_destruct(void* obj)
{
reinterpret_cast<T*>(obj)->~T();
static_cast<T*>(obj)->~T();
}
template <typename T>
void zone::object_delete(void* obj)
{
delete static_cast<T*>(obj);
}
inline void zone::undo_allocate(size_t size)
@@ -346,7 +331,7 @@ T* zone::allocate()
{
void* x = allocate_align(sizeof(T));
try {
m_finalizer_array.push(&zone::object_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -365,7 +350,7 @@ T* zone::allocate(A1 a1)
{
void* x = allocate_align(sizeof(T));
try {
m_finalizer_array.push(&zone::object_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -384,7 +369,7 @@ T* zone::allocate(A1 a1, A2 a2)
{
void* x = allocate_align(sizeof(T));
try {
m_finalizer_array.push(&zone::object_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -403,7 +388,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3)
{
void* x = allocate_align(sizeof(T));
try {
m_finalizer_array.push(&zone::object_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -422,7 +407,7 @@ T* zone::allocate(A1 a1, A2 a2, A3 a3, A4 a4)
{
void* x = allocate_align(sizeof(T));
try {
m_finalizer_array.push(&zone::object_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -441,7 +426,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -460,7 +445,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -479,7 +464,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -498,7 +483,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -517,7 +502,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -536,7 +521,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -555,7 +540,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -574,7 +559,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -593,7 +578,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -612,7 +597,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;
@@ -631,7 +616,7 @@ 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_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;

View File

@@ -91,9 +91,28 @@ private:
++m_tail;
}
#if !defined(MSGPACK_USE_CPP03)
finalizer_array(finalizer_array&& other)
: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)
{
this->~finalizer_array();
new (this) finalizer_array(std::move(other));
return *this;
}
#endif
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;
@@ -114,14 +133,10 @@ private:
~chunk_list()
{
chunk* c = m_head;
while(true) {
while(c) {
chunk* n = c->m_next;
::free(c);
if(n) {
c = n;
} else {
break;
}
c = n;
}
}
void clear(size_t chunk_size)
@@ -141,9 +156,25 @@ private:
m_free = chunk_size;
m_ptr = reinterpret_cast<char*>(m_head) + sizeof(chunk);
}
#if !defined(MSGPACK_USE_CPP03)
chunk_list(chunk_list&& other)
: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)
{
this->~chunk_list();
new (this) chunk_list(std::move(other));
return *this;
}
#endif
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;
@@ -153,8 +184,6 @@ public:
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE) noexcept;
public:
static zone* create(size_t chunk_size);
static void destroy(zone* zone);
void* allocate_align(size_t size);
void* allocate_no_align(size_t size);
@@ -189,31 +218,23 @@ public:
template <typename T, typename... Args>
T* allocate(Args... args);
zone(zone&&) = default;
zone& operator=(zone&&) = default;
private:
void undo_allocate(size_t size);
zone(const zone&);
zone& operator=(const zone&);
template <typename T>
static void object_destructor(void* obj);
static void object_destruct(void* obj);
template <typename T>
static void object_delete(void* obj);
void* allocate_expand(size_t size);
};
inline zone* zone::create(size_t chunk_size)
{
zone* z = static_cast<zone*>(::malloc(sizeof(zone) + chunk_size));
if (!z) {
throw std::bad_alloc();
}
new (z) zone(chunk_size);
return z;
}
inline void zone::destroy(zone* z)
{
z->~zone();
::free(z);
}
inline zone::zone(size_t chunk_size) noexcept:m_chunk_size(chunk_size), m_chunk_list(m_chunk_size)
{
}
@@ -268,8 +289,7 @@ inline void zone::push_finalizer(void (*func)(void*), void* data)
template <typename T>
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj)
{
m_finalizer_array.push(&zone::object_destructor<T>, obj.get());
obj.release();
m_finalizer_array.push(&zone::object_delete<T>, obj.release());
}
inline void zone::clear()
@@ -284,9 +304,15 @@ inline void zone::swap(zone& o)
}
template <typename T>
void zone::object_destructor(void* obj)
void zone::object_delete(void* obj)
{
reinterpret_cast<T*>(obj)->~T();
delete static_cast<T*>(obj);
}
template <typename T>
void zone::object_destruct(void* obj)
{
static_cast<T*>(obj)->~T();
}
inline void zone::undo_allocate(size_t size)
@@ -301,7 +327,7 @@ T* zone::allocate(Args... args)
{
void* x = allocate_align(sizeof(T));
try {
m_finalizer_array.push(&zone::object_destructor<T>, x);
m_finalizer_array.push(&zone::object_destruct<T>, x);
} catch (...) {
undo_allocate(sizeof(T));
throw;

View File

@@ -961,7 +961,7 @@ private:
std::size_t m_free;
std::size_t m_off;
std::size_t m_parsed;
zone* m_z;
msgpack::unique_ptr<zone> m_z;
std::size_t m_initial_buffer_size;
detail::context m_ctx;
@@ -994,7 +994,7 @@ typedef enum {
inline unpacker::unpacker(unpack_reference_func f,
void* user_data,
std::size_t initial_buffer_size)
:m_ctx(f, user_data)
:m_z(new zone), m_ctx(f, user_data)
{
if(initial_buffer_size < COUNTER_SIZE) {
initial_buffer_size = COUNTER_SIZE;
@@ -1005,19 +1005,12 @@ inline unpacker::unpacker(unpack_reference_func f,
throw std::bad_alloc();
}
zone* z = zone::create(MSGPACK_ZONE_CHUNK_SIZE);
if(!z) {
::free(buffer);
throw std::bad_alloc();
}
m_buffer = buffer;
m_used = COUNTER_SIZE;
m_free = initial_buffer_size - m_used;
m_off = COUNTER_SIZE;
m_parsed = 0;
m_initial_buffer_size = initial_buffer_size;
m_z = z;
detail::init_count(m_buffer);
@@ -1035,11 +1028,10 @@ inline unpacker::unpacker(unpacker&& other)
m_free(other.m_free),
m_off(other.m_off),
m_parsed(other.m_parsed),
m_z(other.m_z),
m_z(std::move(other.m_z)),
m_initial_buffer_size(other.m_initial_buffer_size),
m_ctx(other.m_ctx) {
other.m_buffer = nullptr;
other.m_z = nullptr;
}
inline unpacker& unpacker::operator=(unpacker&& other) {
@@ -1054,7 +1046,6 @@ inline unpacker& unpacker::operator=(unpacker&& other) {
inline unpacker::~unpacker()
{
// These checks are required for move operations.
if (m_z) zone::destroy(m_z);
if (m_buffer) detail::decl_count(m_buffer);
}
@@ -1204,13 +1195,9 @@ inline zone* unpacker::release_zone()
return nullptr;
}
zone* r = zone::create(MSGPACK_ZONE_CHUNK_SIZE);
if(!r) {
return nullptr;
}
zone* old = m_z;
m_z = r;
zone* r = new zone;
zone* old = m_z.release();
m_z.reset(r);
m_ctx.user().set_zone(*m_z);
return old;
@@ -1324,7 +1311,7 @@ inline void unpack(unpacked& result,
unpack_reference_func f, void* user_data)
{
object obj;
msgpack::unique_ptr<zone> z(new zone());
msgpack::unique_ptr<zone> z(new zone);
bool referenced = false;
unpack_return ret = detail::unpack_imp(
data, len, off, *z, obj, referenced);

View File

@@ -195,7 +195,7 @@ bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size)
msgpack_zone* msgpack_zone_new(size_t chunk_size)
{
msgpack_zone* zone = (msgpack_zone*)malloc(
sizeof(msgpack_zone) + chunk_size);
sizeof(msgpack_zone));
if(zone == NULL) {
return NULL;
}