diff options
author | frsyuki <frsyuki@users.sourceforge.jp> | 2009-03-01 15:49:24 +0900 |
---|---|---|
committer | frsyuki <frsyuki@users.sourceforge.jp> | 2009-03-01 15:49:24 +0900 |
commit | 21040d9cd3b03ee27248b39a6b657948fdac5f9d (patch) | |
tree | 77a26af7b379b07eae9ccc06d04349e9cc9e2566 | |
parent | 319838e51757b59a9aa9e017491139602bcc1e68 (diff) | |
download | msgpack-python-21040d9cd3b03ee27248b39a6b657948fdac5f9d.tar.gz |
zone::push_finalizer reverts memory allocation on exception
-rw-r--r-- | c/zone.c | 54 | ||||
-rw-r--r-- | c/zone.h | 37 | ||||
-rw-r--r-- | cpp/zone.hpp.erb | 23 |
3 files changed, 74 insertions, 40 deletions
@@ -34,7 +34,7 @@ static inline bool init_chunk_array(msgpack_zone_chunk_array* ca, size_t chunk_s const size_t sz = chunk_size; char* ptr = (char*)malloc(sz); - if(!ptr) { + if(ptr == NULL) { free(array); return NULL; } @@ -88,7 +88,7 @@ void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size) chunk = (msgpack_zone_chunk*)realloc(ca->array, sizeof(msgpack_zone_chunk) * nnext); - if(!chunk) { + if(chunk == NULL) { return NULL; } @@ -104,7 +104,7 @@ void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size) } char* ptr = (char*)malloc(sz); - if(!ptr) { + if(ptr == NULL) { return NULL; } @@ -144,44 +144,38 @@ static inline void clear_finalizer_array(msgpack_zone_finalizer_array* fa) fa->tail = fa->array; } -bool msgpack_zone_push_finalizer(msgpack_zone* zone, +bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone, void (*func)(void* data), void* data) { msgpack_zone_finalizer_array* const fa = &zone->finalizer_array; - msgpack_zone_finalizer* fin = fa->tail; - - if(fin == fa->end) { - // fa->arrayに空きがない - // fa->arrayを拡張する - - size_t nnext; - const size_t nused = fa->end - fa->array; + const size_t nused = fa->end - fa->array; - if(nused == 0) { - // 初回の呼び出し:fa->tail == fa->end == fa->array == NULL + size_t nnext; + if(nused == 0) { + // 初回の呼び出し:fa->tail == fa->end == fa->array == NULL - // glibcは72バイト以下のmallocが高速 - nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ? - 72 / sizeof(msgpack_zone_finalizer) : 8; + // glibcは72バイト以下のmallocが高速 + nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ? + 72 / sizeof(msgpack_zone_finalizer) : 8; - } else { - nnext = (fa->end - fa->array) * 2; - } + } else { + nnext = nused * 2; + } - fin = (msgpack_zone_finalizer*)realloc(fa->array, + msgpack_zone_finalizer* tmp = + (msgpack_zone_finalizer*)realloc(fa->array, sizeof(msgpack_zone_finalizer) * nnext); - if(!fin) { - return false; - } - - fa->array = fin; - fa->end = fin + nnext; - fin = fa->tail = fin + nused; + if(tmp == NULL) { + return false; } - fin->func = func; - fin->data = data; + fa->array = tmp; + fa->end = tmp + nnext; + fa->tail = tmp + nused; + + fa->tail->func = func; + fa->tail->data = data; ++fa->tail; @@ -67,7 +67,7 @@ void msgpack_zone_free(msgpack_zone* zone); static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size); -bool msgpack_zone_push_finalizer(msgpack_zone* zone, +static inline bool msgpack_zone_push_finalizer(msgpack_zone* zone, void (*func)(void* data), void* data); bool msgpack_zone_is_empty(msgpack_zone* zone); @@ -88,14 +88,37 @@ void* msgpack_zone_malloc(msgpack_zone* zone, size_t size) msgpack_zone_chunk* chunk = zone->chunk_array.tail; - if(chunk->free > size) { - char* ptr = chunk->ptr; - chunk->ptr += size; - chunk->free -= size; - return ptr; + if(chunk->free < size) { + return msgpack_zone_malloc_expand(zone, size); + } + + char* ptr = chunk->ptr; + chunk->ptr += size; + chunk->free -= size; + + return ptr; +} + + +bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone, + void (*func)(void* data), void* data); + +bool msgpack_zone_push_finalizer(msgpack_zone* zone, + void (*func)(void* data), void* data) +{ + msgpack_zone_finalizer_array* const fa = &zone->finalizer_array; + msgpack_zone_finalizer* fin = fa->tail; + + if(fin == fa->end) { + return msgpack_zone_push_finalizer_expand(zone, func, data); } - return msgpack_zone_malloc_expand(zone, size); + fin->func = func; + fin->data = data; + + ++fa->tail; + + return true; } diff --git a/cpp/zone.hpp.erb b/cpp/zone.hpp.erb index 930c8e8..874c900 100644 --- a/cpp/zone.hpp.erb +++ b/cpp/zone.hpp.erb @@ -45,6 +45,8 @@ public: <%}%> private: + void undo_malloc(size_t s); + template <typename T> static void object_destructor(void* obj); @@ -91,14 +93,29 @@ void zone::object_destructor(void* obj) reinterpret_cast<T*>(obj)->~T(); } +inline void zone::undo_malloc(size_t s) +{ + msgpack_zone_chunk* chunk = chunk_array.tail; + chunk->ptr -= s; + chunk->free += s; +} + <%0.upto(GENERATION_LIMIT) {|i|%> template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>> T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>) { void* x = malloc(sizeof(T)); - push_finalizer(&zone::object_destructor<T>, x); - try { return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>); } - catch (...) { --finalizer_array.tail; throw; } + if(!msgpack_zone_push_finalizer(this, &zone::object_destructor<T>, x)) { + undo_malloc(sizeof(T)); + throw std::bad_alloc(); + } + try { + return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>); + } catch (...) { + --finalizer_array.tail; + undo_malloc(sizeof(T)); + throw; + } } <%}%> |