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
This commit is contained in:
frsyuki 2009-02-15 09:09:58 +00:00
parent 9923cf4daf
commit b790df530a
4 changed files with 102 additions and 24 deletions

View File

@ -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 = \

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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: