summaryrefslogtreecommitdiff
path: root/cpp/zone.cpp
diff options
context:
space:
mode:
authorfrsyuki <frsyuki@5a5092ae-2292-43ba-b2d5-dcab9c1a2731>2009-02-15 09:10:00 +0000
committerfrsyuki <frsyuki@5a5092ae-2292-43ba-b2d5-dcab9c1a2731>2009-02-15 09:10:00 +0000
commite582fa34c7f1246d27cce5a2333e0f954cbed251 (patch)
tree529597afaef7d1399d39f92b2cc8dede7dcf391c /cpp/zone.cpp
parentc93d45371b2b2a085fa2fe84d6ceb79decf778d2 (diff)
downloadmsgpack-python-e582fa34c7f1246d27cce5a2333e0f954cbed251.tar.gz
c++ binding: improve msgpack::zone, zero-copy stream deserializer
git-svn-id: file:///Users/frsyuki/project/msgpack-git/svn/x@92 5a5092ae-2292-43ba-b2d5-dcab9c1a2731
Diffstat (limited to 'cpp/zone.cpp')
-rw-r--r--cpp/zone.cpp82
1 files changed, 67 insertions, 15 deletions
diff --git a/cpp/zone.cpp b/cpp/zone.cpp
index 527cc9c..7c5a1c9 100644
--- a/cpp/zone.cpp
+++ b/cpp/zone.cpp
@@ -16,31 +16,83 @@
// limitations under the License.
//
#include "msgpack/zone.hpp"
+#include <algorithm>
namespace msgpack {
-void zone::clear()
+zone::zone(size_t chunk_size) :
+ m_chunk_size(chunk_size)
{
- for(std::vector<char*>::iterator it(m_ptrs.begin()), it_end(m_ptrs.end());
- it != it_end; ++it) {
- free(*it);
- }
- m_ptrs.clear();
+ chunk dummy = {0, NULL, NULL};
+ m_chunk_array.push_back(dummy);
}
-char* zone::realloc_real(char* ptr, size_t count)
+zone::~zone()
{
- for(std::vector<char*>::reverse_iterator it(m_ptrs.rbegin()), it_end(m_ptrs.rend());
- it != it_end; ++it) {
- if(*it == ptr) {
- char* tmp = (char*)::realloc(ptr, count);
- if(!tmp) { throw std::bad_alloc(); }
- *it = tmp;
- return tmp;
+ clear();
+}
+
+namespace {
+ template <typename Private>
+ struct zone_finalize {
+ void operator() (Private& f) {
+ (*f.func)(f.obj);
+ }
+ };
+
+ template <typename Private>
+ struct zone_free {
+ void operator() (Private& c) {
+ ::free(c.alloc);
}
+ };
+}
+
+void zone::clear()
+{
+ std::for_each(m_finalizers.rbegin(), m_finalizers.rend(),
+ zone_finalize<finalizer>());
+ m_finalizers.clear();
+
+ std::for_each(m_chunk_array.begin(), m_chunk_array.end(),
+ zone_free<chunk>());
+ m_chunk_array.resize(1);
+ m_chunk_array[0].ptr = NULL;
+ m_chunk_array[0].free = 0;
+}
+
+bool zone::empty() const
+{
+ return m_chunk_array.back().alloc == NULL &&
+ m_finalizers.empty();
+}
+
+void* zone::malloc(size_t size)
+{
+ if(m_chunk_array.back().free > size) {
+ char* p = (char*)m_chunk_array.back().ptr;
+ m_chunk_array.back().ptr = p + size;
+ m_chunk_array.back().free -= size;
+ return p;
}
- throw std::bad_alloc();
+
+ size_t sz = m_chunk_size;
+ while(sz < size) { sz *= 2; }
+
+ chunk dummy = {0, NULL, NULL};
+ m_chunk_array.push_back(dummy);
+
+ char* p = (char*)::malloc(sz);
+ if(!p) {
+ m_chunk_array.pop_back();
+ throw std::bad_alloc();
+ }
+
+ m_chunk_array.back().free = sz - size;
+ m_chunk_array.back().ptr = p + size;
+ m_chunk_array.back().alloc = p;
+ return p;
}