mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-14 06:55:50 +02: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:
@@ -14,9 +14,11 @@ nobase_include_HEADERS = \
|
|||||||
msgpack/type.hpp \
|
msgpack/type.hpp \
|
||||||
msgpack/type/array.hpp \
|
msgpack/type/array.hpp \
|
||||||
msgpack/type/boolean.hpp \
|
msgpack/type/boolean.hpp \
|
||||||
|
msgpack/type/float.hpp \
|
||||||
msgpack/type/integer.hpp \
|
msgpack/type/integer.hpp \
|
||||||
msgpack/type/map.hpp \
|
msgpack/type/map.hpp \
|
||||||
msgpack/type/nil.hpp \
|
msgpack/type/nil.hpp \
|
||||||
|
msgpack/type/raw.hpp \
|
||||||
msgpack/type/tuple.hpp
|
msgpack/type/tuple.hpp
|
||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
|
16
cpp/test.cpp
16
cpp/test.cpp
@@ -152,9 +152,7 @@ int main(void)
|
|||||||
unsigned num_msg = 0;
|
unsigned num_msg = 0;
|
||||||
static const size_t RESERVE_SIZE = 32;//*1024;
|
static const size_t RESERVE_SIZE = 32;//*1024;
|
||||||
|
|
||||||
std::auto_ptr<zone> pz(new zone());
|
unpacker pac;
|
||||||
|
|
||||||
unpacker pac(*pz);
|
|
||||||
|
|
||||||
while(stream.good() && total_bytes > 0) {
|
while(stream.good() && total_bytes > 0) {
|
||||||
|
|
||||||
@@ -179,13 +177,15 @@ int main(void)
|
|||||||
// 5.1. take out the parsed object
|
// 5.1. take out the parsed object
|
||||||
object o = pac.data();
|
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;
|
std::cout << "message parsed: " << o << std::endl;
|
||||||
++num_msg;
|
++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) :
|
unpacker::unpacker() :
|
||||||
m_ctx(new context(&z)),
|
|
||||||
m_buffer(NULL),
|
m_buffer(NULL),
|
||||||
m_used(0),
|
m_used(0),
|
||||||
m_free(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; }
|
else { next_size = UNPACKER_INITIAL_BUFFER_SIZE; }
|
||||||
while(next_size < len + m_used) { next_size *= 2; }
|
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;
|
m_free = next_size - m_used;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
size_t next_size = UNPACKER_INITIAL_BUFFER_SIZE;
|
size_t next_size = UNPACKER_INITIAL_BUFFER_SIZE;
|
||||||
while(next_size < len + m_used - m_off) { next_size *= 2; }
|
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);
|
memcpy(tmp, m_buffer+m_off, m_used-m_off);
|
||||||
|
|
||||||
m_buffer = tmp;
|
m_buffer = tmp;
|
||||||
@@ -226,20 +227,49 @@ bool unpacker::execute()
|
|||||||
} else if(ret == 0) {
|
} else if(ret == 0) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
expand_buffer(0);
|
|
||||||
return true;
|
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()
|
object unpacker::data()
|
||||||
{
|
{
|
||||||
return m_ctx->data();
|
return m_ctx->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void unpacker::reset(zone& z)
|
void unpacker::reset()
|
||||||
{
|
{
|
||||||
if(m_off != 0) { expand_buffer(0); }
|
if(m_off != 0) { std::auto_ptr<zone> old(release_zone()); }
|
||||||
m_ctx->reset(&z);
|
m_ctx->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "msgpack/object.hpp"
|
#include "msgpack/object.hpp"
|
||||||
#include "msgpack/zone.hpp"
|
#include "msgpack/zone.hpp"
|
||||||
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#ifndef MSGPACK_UNPACKER_INITIAL_BUFFER_SIZE
|
#ifndef MSGPACK_UNPACKER_INITIAL_BUFFER_SIZE
|
||||||
@@ -40,7 +41,7 @@ struct unpack_error : public std::runtime_error {
|
|||||||
|
|
||||||
class unpacker {
|
class unpacker {
|
||||||
public:
|
public:
|
||||||
unpacker(zone& z);
|
unpacker();
|
||||||
~unpacker();
|
~unpacker();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -60,8 +61,52 @@ public:
|
|||||||
/*! 5.1. if execute() returns true, take out the parsed object */
|
/*! 5.1. if execute() returns true, take out the parsed object */
|
||||||
object data();
|
object data();
|
||||||
|
|
||||||
/*! 5.2. re-initialize unpacker with next zone */
|
/*! 5.2. the object is valid until the zone is deleted */
|
||||||
void reset(zone& z);
|
// 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:
|
public:
|
||||||
// These functions are usable when non-MessagePack message follows after
|
// These functions are usable when non-MessagePack message follows after
|
||||||
@@ -80,19 +125,20 @@ public:
|
|||||||
void remove_nonparsed_buffer();
|
void remove_nonparsed_buffer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct context;
|
|
||||||
context* m_ctx;
|
|
||||||
|
|
||||||
char* m_buffer;
|
char* m_buffer;
|
||||||
size_t m_used;
|
size_t m_used;
|
||||||
size_t m_free;
|
size_t m_free;
|
||||||
size_t m_off;
|
size_t m_off;
|
||||||
|
|
||||||
|
std::auto_ptr<zone> m_zone;
|
||||||
|
|
||||||
|
struct context;
|
||||||
|
context* m_ctx;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void expand_buffer(size_t len);
|
void expand_buffer(size_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unpacker();
|
|
||||||
unpacker(const unpacker&);
|
unpacker(const unpacker&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Reference in New Issue
Block a user