mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-19 13:02:13 +01:00
zone::push_finalizer reverts memory allocation on exception
This commit is contained in:
parent
e7403013e5
commit
e707b7a600
58
c/zone.c
58
c/zone.c
@ -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;
|
||||
const size_t nused = fa->end - fa->array;
|
||||
|
||||
if(fin == fa->end) {
|
||||
// fa->arrayに空きがない
|
||||
// fa->arrayを拡張する
|
||||
size_t nnext;
|
||||
if(nused == 0) {
|
||||
// 初回の呼び出し:fa->tail == fa->end == fa->array == NULL
|
||||
|
||||
size_t nnext;
|
||||
const size_t nused = fa->end - fa->array;
|
||||
// glibcは72バイト以下のmallocが高速
|
||||
nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ?
|
||||
72 / sizeof(msgpack_zone_finalizer) : 8;
|
||||
|
||||
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;
|
||||
|
||||
} else {
|
||||
nnext = (fa->end - fa->array) * 2;
|
||||
}
|
||||
|
||||
fin = (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;
|
||||
} else {
|
||||
nnext = nused * 2;
|
||||
}
|
||||
|
||||
fin->func = func;
|
||||
fin->data = data;
|
||||
msgpack_zone_finalizer* tmp =
|
||||
(msgpack_zone_finalizer*)realloc(fa->array,
|
||||
sizeof(msgpack_zone_finalizer) * nnext);
|
||||
if(tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fa->array = tmp;
|
||||
fa->end = tmp + nnext;
|
||||
fa->tail = tmp + nused;
|
||||
|
||||
fa->tail->func = func;
|
||||
fa->tail->data = data;
|
||||
|
||||
++fa->tail;
|
||||
|
||||
|
37
c/zone.h
37
c/zone.h
@ -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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
fin->func = func;
|
||||
fin->data = data;
|
||||
|
||||
++fa->tail;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
<%}%>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user