mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-14 18:10:30 +01:00
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:
parent
9923cf4daf
commit
b790df530a
@ -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 = \
|
||||
|
16
cpp/test.cpp
16
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user