2009-02-15 09:09:57 +00:00
|
|
|
//
|
|
|
|
// MessagePack for C++ memory pool
|
|
|
|
//
|
|
|
|
// Copyright (C) 2008 FURUHASHI Sadayuki
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
//
|
2009-02-15 09:09:56 +00:00
|
|
|
#ifndef MSGPACK_ZONE_HPP__
|
|
|
|
#define MSGPACK_ZONE_HPP__
|
2009-02-15 09:09:56 +00:00
|
|
|
#include <iostream>
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
#include "msgpack/object.hpp"
|
2009-02-15 09:09:56 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdexcept>
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
#ifndef MSGPACK_ZONE_CHUNK_SIZE
|
2009-02-15 09:09:56 +00:00
|
|
|
#define MSGPACK_ZONE_CHUNK_SIZE 8*1024
|
2009-02-15 09:09:56 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace msgpack {
|
|
|
|
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
static const size_t ZONE_CHUNK_SIZE = MSGPACK_ZONE_CHUNK_SIZE;
|
|
|
|
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
class zone {
|
|
|
|
public:
|
2009-02-15 09:09:56 +00:00
|
|
|
zone() : m_used(0) { }
|
|
|
|
~zone() { clear(); }
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
template <typename T>
|
|
|
|
void push_finalizer(void (*func)(void* obj, void* user), T* obj, void* user);
|
|
|
|
|
|
|
|
public:
|
|
|
|
object_nil* nnil() { return new (alloc()) object_nil(); }
|
|
|
|
object_true* ntrue() { return new (alloc()) object_true(); }
|
|
|
|
object_false* nfalse() { return new (alloc()) object_false(); }
|
|
|
|
object_u8* nu8( uint8_t v) { return new (alloc()) object_u8(v); }
|
|
|
|
object_u16* nu16(uint16_t v) { return new (alloc()) object_u16(v); }
|
|
|
|
object_u32* nu32(uint32_t v) { return new (alloc()) object_u32(v); }
|
|
|
|
object_u64* nu64(uint64_t v) { return new (alloc()) object_u64(v); }
|
|
|
|
object_i8* ni8( int8_t v) { return new (alloc()) object_i8(v); }
|
|
|
|
object_i16* ni16( int16_t v) { return new (alloc()) object_i16(v); }
|
|
|
|
object_i32* ni32( int32_t v) { return new (alloc()) object_i32(v); }
|
|
|
|
object_i64* ni64( int64_t v) { return new (alloc()) object_i64(v); }
|
|
|
|
object_float* nfloat( float v) { return new (alloc()) object_float(v); }
|
|
|
|
object_double* ndouble( double v) { return new (alloc()) object_double(v); }
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
object_raw_ref* nraw_ref(void* ptr, uint32_t len)
|
|
|
|
{ return new (alloc()) object_raw_ref(ptr, len); }
|
|
|
|
|
|
|
|
object_const_raw_ref* nraw_ref(const void* ptr, uint32_t len)
|
|
|
|
{ return new (alloc()) object_const_raw_ref(ptr, len); }
|
|
|
|
|
|
|
|
object_raw_ref* nraw_copy(const void* ptr, uint32_t len)
|
|
|
|
{
|
|
|
|
void* copy = malloc(len);
|
|
|
|
if(!copy) { throw std::bad_alloc(); }
|
|
|
|
object_raw_ref* o;
|
|
|
|
try {
|
|
|
|
o = new (alloc()) object_raw_ref(copy, len);
|
|
|
|
push_finalizer<void>(&zone::finalize_free, NULL, copy);
|
|
|
|
} catch (...) {
|
|
|
|
free(copy);
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
memcpy(copy, ptr, len);
|
|
|
|
return o;
|
|
|
|
}
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
object_array* narray()
|
|
|
|
{ return new (alloc()) object_array(); }
|
|
|
|
|
|
|
|
object_array* narray(size_t reserve_size)
|
|
|
|
{ return new (alloc()) object_array(reserve_size); }
|
|
|
|
|
|
|
|
object_map* nmap()
|
|
|
|
{ return new (alloc()) object_map(); }
|
|
|
|
|
|
|
|
<% GENERATION_SIZE = 16 %>
|
|
|
|
<% 1.upto(GENERATION_SIZE) {|i| %>
|
|
|
|
object_array* narray(<% 1.upto(i-1) {|n| %>object o<%=n%>, <% } %>object o<%=i%>)
|
|
|
|
{ object_array* a = new (alloc()) object_array(<%=i%>);
|
|
|
|
<% 1.upto(i) {|n| %>a->push_back(o<%=n%>);
|
|
|
|
<% } %>return a; }
|
|
|
|
<% } %>
|
|
|
|
|
|
|
|
<% 1.upto(GENERATION_SIZE) {|i| %>
|
|
|
|
object_map* nmap(<% 1.upto(i-1) {|n| %>object k<%=n%>, object v<%=n%>, <% } %>object k<%=i%>, object v<%=i%>)
|
|
|
|
{ object_map* m = new (alloc()) object_map();
|
|
|
|
<% 1.upto(i) {|n| %>m->store(k<%=n%>, v<%=n%>);
|
|
|
|
<% } %>return m; }
|
|
|
|
<% } %>
|
|
|
|
|
|
|
|
public:
|
|
|
|
void clear();
|
2009-02-15 09:09:56 +00:00
|
|
|
bool empty() const;
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
void* alloc();
|
|
|
|
|
|
|
|
private:
|
|
|
|
size_t m_used;
|
|
|
|
|
|
|
|
static const size_t MAX_OBJECT_SIZE =
|
2009-02-15 09:09:56 +00:00
|
|
|
sizeof(object_raw_ref) > sizeof(object_array)
|
|
|
|
? ( sizeof(object_raw_ref) > sizeof(object_map)
|
|
|
|
? sizeof(object_raw_ref)
|
2009-02-15 09:09:56 +00:00
|
|
|
: sizeof(object_map)
|
|
|
|
)
|
|
|
|
: ( sizeof(object_array) > sizeof(object_map)
|
|
|
|
? sizeof(object_array)
|
|
|
|
: sizeof(object_map)
|
|
|
|
)
|
|
|
|
;
|
|
|
|
|
|
|
|
struct cell_t {
|
|
|
|
char data[MAX_OBJECT_SIZE];
|
|
|
|
};
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
typedef std::vector<cell_t*> pool_t;
|
2009-02-15 09:09:56 +00:00
|
|
|
pool_t m_pool;
|
|
|
|
|
|
|
|
|
|
|
|
class finalizer {
|
|
|
|
public:
|
|
|
|
finalizer(void (*func)(void*, void*), void* obj, void* user) :
|
|
|
|
m_obj(obj), m_user(user), m_func(func) {}
|
|
|
|
void call() { (*m_func)(m_obj, m_user); }
|
|
|
|
private:
|
|
|
|
void* m_obj;
|
|
|
|
void* m_user;
|
|
|
|
void (*m_func)(void*, void*);
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<finalizer> user_finalizer_t;
|
|
|
|
user_finalizer_t m_user_finalizer;
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
private:
|
|
|
|
void resize_pool(size_t n);
|
|
|
|
|
|
|
|
public:
|
|
|
|
static void finalize_free(void* obj, void* user)
|
|
|
|
{ free(user); }
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
private:
|
|
|
|
zone(const zone&);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
template <typename T>
|
|
|
|
inline void zone::push_finalizer(void (*func)(void* obj, void* user), T* obj, void* user)
|
|
|
|
{
|
|
|
|
m_user_finalizer.push_back( finalizer(
|
|
|
|
func, reinterpret_cast<void*>(obj),
|
|
|
|
user) );
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool zone::empty() const
|
|
|
|
{
|
|
|
|
return m_used == 0 && m_user_finalizer.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
} // namespace msgpack
|
|
|
|
|
|
|
|
#endif /* msgpack/zone.hpp */
|
|
|
|
|