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;
|
const size_t sz = chunk_size;
|
||||||
|
|
||||||
char* ptr = (char*)malloc(sz);
|
char* ptr = (char*)malloc(sz);
|
||||||
if(!ptr) {
|
if(ptr == NULL) {
|
||||||
free(array);
|
free(array);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size)
|
|||||||
|
|
||||||
chunk = (msgpack_zone_chunk*)realloc(ca->array,
|
chunk = (msgpack_zone_chunk*)realloc(ca->array,
|
||||||
sizeof(msgpack_zone_chunk) * nnext);
|
sizeof(msgpack_zone_chunk) * nnext);
|
||||||
if(!chunk) {
|
if(chunk == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char* ptr = (char*)malloc(sz);
|
char* ptr = (char*)malloc(sz);
|
||||||
if(!ptr) {
|
if(ptr == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,44 +144,38 @@ static inline void clear_finalizer_array(msgpack_zone_finalizer_array* fa)
|
|||||||
fa->tail = fa->array;
|
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)
|
void (*func)(void* data), void* data)
|
||||||
{
|
{
|
||||||
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
|
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) {
|
size_t nnext;
|
||||||
// fa->arrayに空きがない
|
if(nused == 0) {
|
||||||
// fa->arrayを拡張する
|
// 初回の呼び出し:fa->tail == fa->end == fa->array == NULL
|
||||||
|
|
||||||
size_t nnext;
|
// glibcは72バイト以下のmallocが高速
|
||||||
const size_t nused = fa->end - fa->array;
|
nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ?
|
||||||
|
72 / sizeof(msgpack_zone_finalizer) : 8;
|
||||||
|
|
||||||
if(nused == 0) {
|
} else {
|
||||||
// 初回の呼び出し:fa->tail == fa->end == fa->array == NULL
|
nnext = nused * 2;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fin->func = func;
|
msgpack_zone_finalizer* tmp =
|
||||||
fin->data = data;
|
(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;
|
++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);
|
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);
|
void (*func)(void* data), void* data);
|
||||||
|
|
||||||
bool msgpack_zone_is_empty(msgpack_zone* zone);
|
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;
|
msgpack_zone_chunk* chunk = zone->chunk_array.tail;
|
||||||
|
|
||||||
if(chunk->free > size) {
|
if(chunk->free < size) {
|
||||||
char* ptr = chunk->ptr;
|
return msgpack_zone_malloc_expand(zone, size);
|
||||||
chunk->ptr += size;
|
|
||||||
chunk->free -= size;
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
private:
|
||||||
|
void undo_malloc(size_t s);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void object_destructor(void* obj);
|
static void object_destructor(void* obj);
|
||||||
|
|
||||||
@ -91,14 +93,29 @@ void zone::object_destructor(void* obj)
|
|||||||
reinterpret_cast<T*>(obj)->~T();
|
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|%>
|
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||||
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||||
T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
|
T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
|
||||||
{
|
{
|
||||||
void* x = malloc(sizeof(T));
|
void* x = malloc(sizeof(T));
|
||||||
push_finalizer(&zone::object_destructor<T>, x);
|
if(!msgpack_zone_push_finalizer(this, &zone::object_destructor<T>, x)) {
|
||||||
try { return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>); }
|
undo_malloc(sizeof(T));
|
||||||
catch (...) { --finalizer_array.tail; throw; }
|
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