diff options
author | frsyuki <frsyuki@5a5092ae-2292-43ba-b2d5-dcab9c1a2731> | 2009-02-15 09:09:58 +0000 |
---|---|---|
committer | frsyuki <frsyuki@5a5092ae-2292-43ba-b2d5-dcab9c1a2731> | 2009-02-15 09:09:58 +0000 |
commit | b790df530aa28099aa130dafad0a591004b88650 (patch) | |
tree | 4d09f4c43a5994bcf83e152471e29ac9c952ba3e | |
parent | 9923cf4daf631432e389dd0694042b6b405c1288 (diff) | |
download | msgpack-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.am | 2 | ||||
-rw-r--r-- | cpp/test.cpp | 16 | ||||
-rw-r--r-- | cpp/unpack.cpp | 48 | ||||
-rw-r--r-- | cpp/unpack.hpp | 60 |
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: |