summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfrsyuki <frsyuki@5a5092ae-2292-43ba-b2d5-dcab9c1a2731>2009-02-15 09:09:58 +0000
committerfrsyuki <frsyuki@5a5092ae-2292-43ba-b2d5-dcab9c1a2731>2009-02-15 09:09:58 +0000
commitb790df530aa28099aa130dafad0a591004b88650 (patch)
tree4d09f4c43a5994bcf83e152471e29ac9c952ba3e
parent9923cf4daf631432e389dd0694042b6b405c1288 (diff)
downloadmsgpack-python-b790df530aa28099aa130dafad0a591004b88650.tar.gz
lang/c/msgpack: C++ binding: safer memory managent
git-svn-id: file:///Users/frsyuki/project/msgpack-git/svn/x@68 5a5092ae-2292-43ba-b2d5-dcab9c1a2731
-rw-r--r--cpp/Makefile.am2
-rw-r--r--cpp/test.cpp16
-rw-r--r--cpp/unpack.cpp48
-rw-r--r--cpp/unpack.hpp60
4 files changed, 102 insertions, 24 deletions
diff --git a/cpp/Makefile.am b/cpp/Makefile.am
index 8b13bea..e244763 100644
--- a/cpp/Makefile.am
+++ b/cpp/Makefile.am
@@ -14,9 +14,11 @@ nobase_include_HEADERS = \
msgpack/type.hpp \
msgpack/type/array.hpp \
msgpack/type/boolean.hpp \
+ msgpack/type/float.hpp \
msgpack/type/integer.hpp \
msgpack/type/map.hpp \
msgpack/type/nil.hpp \
+ msgpack/type/raw.hpp \
msgpack/type/tuple.hpp
noinst_HEADERS = \
diff --git a/cpp/test.cpp b/cpp/test.cpp
index dff9101..c632ec5 100644
--- a/cpp/test.cpp
+++ b/cpp/test.cpp
@@ -152,9 +152,7 @@ int main(void)
unsigned num_msg = 0;
static const size_t RESERVE_SIZE = 32;//*1024;
- std::auto_ptr<zone> pz(new zone());
-
- unpacker pac(*pz);
+ unpacker pac;
while(stream.good() && total_bytes > 0) {
@@ -179,13 +177,15 @@ int main(void)
// 5.1. take out the parsed object
object o = pac.data();
- // do something using pz and o
+ // 5.2 release the zone
+ std::auto_ptr<zone> olife( pac.release_zone() );
+
+ // 5.3 re-initialize the unpacker */
+ pac.reset();
+
+ // do some with the o and olife
std::cout << "message parsed: " << o << std::endl;
++num_msg;
-
- // 5.3 re-initialize unpacker with next zone */
- pz.reset(new zone());
- pac.reset(*pz);
}
}
diff --git a/cpp/unpack.cpp b/cpp/unpack.cpp
index 71593a0..ce39afd 100644
--- a/cpp/unpack.cpp
+++ b/cpp/unpack.cpp
@@ -178,12 +178,13 @@ private:
};
-unpacker::unpacker(zone& z) :
- m_ctx(new context(&z)),
+unpacker::unpacker() :
m_buffer(NULL),
m_used(0),
m_free(0),
- m_off(0)
+ m_off(0),
+ m_zone(new zone()),
+ m_ctx(new context(&*m_zone))
{ }
@@ -201,14 +202,14 @@ void unpacker::expand_buffer(size_t len)
else { next_size = UNPACKER_INITIAL_BUFFER_SIZE; }
while(next_size < len + m_used) { next_size *= 2; }
- m_buffer = m_ctx->user()->realloc(m_buffer, next_size);
+ m_buffer = m_zone->realloc(m_buffer, next_size);
m_free = next_size - m_used;
} else {
size_t next_size = UNPACKER_INITIAL_BUFFER_SIZE;
while(next_size < len + m_used - m_off) { next_size *= 2; }
- char* tmp = m_ctx->user()->malloc(next_size);
+ char* tmp = m_zone->malloc(next_size);
memcpy(tmp, m_buffer+m_off, m_used-m_off);
m_buffer = tmp;
@@ -226,20 +227,49 @@ bool unpacker::execute()
} else if(ret == 0) {
return false;
} else {
- expand_buffer(0);
return true;
}
}
+zone* unpacker::release_zone()
+{
+ zone* n = new zone();
+ std::auto_ptr<zone> old(m_zone.release());
+ m_zone.reset(n);
+
+ //std::auto_ptr<zone> old(new zone());
+ //m_zone.swap(old);
+
+ // move all bytes in m_buffer to new buffer from the new zone
+ if(m_used <= m_off) {
+ m_buffer = NULL;
+ m_used = 0;
+ m_free = 0;
+ m_off = 0;
+ } else {
+ try {
+ expand_buffer(0);
+ } catch (...) {
+ // m_zone.swap(old);
+ zone* tmp = old.release();
+ old.reset(m_zone.release());
+ m_zone.reset(tmp);
+ throw;
+ }
+ }
+ m_ctx->user(&*m_zone);
+ return old.release();
+}
+
object unpacker::data()
{
return m_ctx->data();
}
-void unpacker::reset(zone& z)
+void unpacker::reset()
{
- if(m_off != 0) { expand_buffer(0); }
- m_ctx->reset(&z);
+ if(m_off != 0) { std::auto_ptr<zone> old(release_zone()); }
+ m_ctx->reset();
}
diff --git a/cpp/unpack.hpp b/cpp/unpack.hpp
index 2730a08..07c52e7 100644
--- a/cpp/unpack.hpp
+++ b/cpp/unpack.hpp
@@ -20,6 +20,7 @@
#include "msgpack/object.hpp"
#include "msgpack/zone.hpp"
+#include <memory>
#include <stdexcept>
#ifndef MSGPACK_UNPACKER_INITIAL_BUFFER_SIZE
@@ -40,7 +41,7 @@ struct unpack_error : public std::runtime_error {
class unpacker {
public:
- unpacker(zone& z);
+ unpacker();
~unpacker();
public:
@@ -60,8 +61,52 @@ public:
/*! 5.1. if execute() returns true, take out the parsed object */
object data();
- /*! 5.2. re-initialize unpacker with next zone */
- void reset(zone& z);
+ /*! 5.2. the object is valid until the zone is deleted */
+ // Note that once release_zone() from unpacker, you must delete it
+ // otherwise the memrory will leak.
+ zone* release_zone();
+
+ /*! 5.3. after release_zone(), re-initialize unpacker */
+ void reset();
+
+
+ // Basic usage of the unpacker is as following:
+ //
+ // msgpack::unpacker pac;
+ //
+ // while( /* readable */ ) {
+ //
+ // // 1.
+ // pac.reserve(1024);
+ //
+ // // 2.
+ // ssize_t bytes =
+ // read(the_source, pac.buffer, pac.buffer_capacity());
+ //
+ // // error handling ...
+ //
+ // // 3.
+ // pac.buffer_consumed(bytes);
+ //
+ // // 4.
+ // while(pac.execute()) {
+ // // 5.1
+ // object o = pac.data();
+ //
+ // // 5.2
+ // std::auto_ptr<msgpack::zone> olife( pac.release_zone() );
+ //
+ // // boost::shared_ptr is also usable:
+ // // boost::shared_ptr<msgpack::zone> olife( pac.release_zone() );
+ //
+ // // 5.3
+ // pac.reset();
+ //
+ // // do some with the object with the old zone.
+ // do_something(o, olife);
+ // }
+ // }
+ //
public:
// These functions are usable when non-MessagePack message follows after
@@ -80,19 +125,20 @@ public:
void remove_nonparsed_buffer();
private:
- struct context;
- context* m_ctx;
-
char* m_buffer;
size_t m_used;
size_t m_free;
size_t m_off;
+ std::auto_ptr<zone> m_zone;
+
+ struct context;
+ context* m_ctx;
+
private:
void expand_buffer(size_t len);
private:
- unpacker();
unpacker(const unpacker&);
public: