diff --git a/c/unpack.c b/c/unpack.c index e90a29af..f1b3bb1f 100644 --- a/c/unpack.c +++ b/c/unpack.c @@ -337,6 +337,11 @@ msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac) return old; } +void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac) +{ + msgpack_zone_clear(mpac->z); +} + bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac) { if(CTX_REFERENCED(mpac)) { diff --git a/c/unpack.h b/c/unpack.h index a9caf07b..ef637744 100644 --- a/c/unpack.h +++ b/c/unpack.h @@ -58,6 +58,8 @@ msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac); msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac); +void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac); + void msgpack_unpacker_reset(msgpack_unpacker* mpac); static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac); diff --git a/c/zone.c b/c/zone.c index e891c821..7a275f6e 100644 --- a/c/zone.c +++ b/c/zone.c @@ -57,9 +57,23 @@ static inline void destroy_chunk_array(msgpack_zone_chunk_array* ca) for(; chunk != ca->tail+1; ++chunk) { free(chunk->alloc); } + free(ca->array); } +static inline void clear_chunk_array(msgpack_zone_chunk_array* ca) +{ + msgpack_zone_chunk* chunk = ca->array + 1; + for(; chunk != ca->tail+1; ++chunk) { + free(chunk->alloc); + } + + ca->tail = ca->array; + + ca->array[0].free += ca->array[0].ptr - (char*)ca->array[0].alloc; + ca->array[0].ptr = (char*)ca->array[0].alloc; +} + void* msgpack_zone_malloc(msgpack_zone* zone, size_t size) { msgpack_zone_chunk_array* const ca = &zone->chunk_array; @@ -124,16 +138,27 @@ static inline void init_finalizer_array(msgpack_zone_finalizer_array* fa) fa->array = NULL; } -static inline void destroy_finalizer_array(msgpack_zone_finalizer_array* fa) +static inline void call_finalizer_array(msgpack_zone_finalizer_array* fa) { // 逆順に呼び出し msgpack_zone_finalizer* fin = fa->tail; for(; fin != fa->array; --fin) { (*(fin-1)->func)((fin-1)->data); } +} + +static inline void destroy_finalizer_array(msgpack_zone_finalizer_array* fa) +{ + call_finalizer_array(fa); free(fa->array); } +static inline void clear_finalizer_array(msgpack_zone_finalizer_array* fa) +{ + call_finalizer_array(fa); + fa->tail = fa->array; +} + bool msgpack_zone_push_finalizer(msgpack_zone* zone, void (*func)(void* data), void* data) { @@ -208,6 +233,11 @@ void msgpack_zone_destroy(msgpack_zone* zone) destroy_chunk_array(&zone->chunk_array); } +void msgpack_zone_clear(msgpack_zone* zone) +{ + clear_finalizer_array(&zone->finalizer_array); + clear_chunk_array(&zone->chunk_array); +} msgpack_zone* msgpack_zone_new(size_t chunk_size) { diff --git a/c/zone.h b/c/zone.h index 3dc9f524..3c1188df 100644 --- a/c/zone.h +++ b/c/zone.h @@ -72,6 +72,8 @@ bool msgpack_zone_push_finalizer(msgpack_zone* zone, bool msgpack_zone_is_empty(msgpack_zone* zone); +void msgpack_zone_clear(msgpack_zone* zone); + #ifdef __cplusplus } diff --git a/cpp/unpack.hpp b/cpp/unpack.hpp index 38ac7ac8..324111a5 100644 --- a/cpp/unpack.hpp +++ b/cpp/unpack.hpp @@ -64,6 +64,9 @@ public: // otherwise the memrory will leak. zone* release_zone(); + /*! 5.2. this method is equivalence to `delete release_zone()` */ + void reset_zone(); + /*! 5.3. after release_zone(), re-initialize unpacker */ void reset(); @@ -217,6 +220,11 @@ inline zone* unpacker::release_zone() return r; } +inline void unpacker::reset_zone() +{ + msgpack_unpacker_reset_zone(this); +} + inline void unpacker::reset() { msgpack_unpacker_reset(this); diff --git a/cpp/zone.hpp.erb b/cpp/zone.hpp.erb index a2536270..930c8e8a 100644 --- a/cpp/zone.hpp.erb +++ b/cpp/zone.hpp.erb @@ -37,6 +37,8 @@ public: void push_finalizer(void (*func)(void*), void* data); + void clear(); + <%0.upto(GENERATION_LIMIT) {|i|%> template , typename A<%=j%><%}%>> T* allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>); @@ -78,6 +80,11 @@ inline void zone::push_finalizer(void (*func)(void*), void* data) } } +inline void zone::clear() +{ + msgpack_zone_clear(this); +} + template void zone::object_destructor(void* obj) {