summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorfrsyuki <frsyuki@users.sourceforge.jp>2009-03-01 15:49:24 +0900
committerfrsyuki <frsyuki@users.sourceforge.jp>2009-03-01 15:49:24 +0900
commit21040d9cd3b03ee27248b39a6b657948fdac5f9d (patch)
tree77a26af7b379b07eae9ccc06d04349e9cc9e2566 /cpp
parent319838e51757b59a9aa9e017491139602bcc1e68 (diff)
downloadmsgpack-python-21040d9cd3b03ee27248b39a6b657948fdac5f9d.tar.gz
zone::push_finalizer reverts memory allocation on exception
Diffstat (limited to 'cpp')
-rw-r--r--cpp/zone.hpp.erb23
1 files changed, 20 insertions, 3 deletions
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;
+ }
}
<%}%>