root/lang/c/msgpack/trunk/cpp/zone.hpp.erb @ 18838

Revision 18838, 5.0 kB (checked in by frsyuki, 6 years ago)

lang/c/msgpack: optimize zone::alloc()

Line 
1//
2// MessagePack for C++ memory pool
3//
4// Copyright (C) 2008 FURUHASHI Sadayuki
5//
6//    Licensed under the Apache License, Version 2.0 (the "License");
7//    you may not use this file except in compliance with the License.
8//    You may obtain a copy of the License at
9//
10//        http://www.apache.org/licenses/LICENSE-2.0
11//
12//    Unless required by applicable law or agreed to in writing, software
13//    distributed under the License is distributed on an "AS IS" BASIS,
14//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//    See the License for the specific language governing permissions and
16//    limitations under the License.
17//
18#ifndef MSGPACK_ZONE_HPP__
19#define MSGPACK_ZONE_HPP__
20#include <iostream>
21
22#include "msgpack/object.hpp"
23#include <string.h>
24#include <stdlib.h>
25#include <stdexcept>
26
27#ifndef MSGPACK_ZONE_CHUNK_SIZE
28#define MSGPACK_ZONE_CHUNK_SIZE 1024
29#endif
30
31namespace msgpack {
32
33
34static const size_t ZONE_CHUNK_SIZE = MSGPACK_ZONE_CHUNK_SIZE;
35
36
37class zone {
38public:
39        zone() : m_used(0) { }
40        ~zone() { clear(); }
41
42public:
43        template <typename T>
44        void push_finalizer(void (*func)(void* obj, void* user), T* obj, void* user);
45
46public:
47        object_nil*    nnil   () { return new (alloc()) object_nil();   }
48        object_true*   ntrue  () { return new (alloc()) object_true();  }
49        object_false*  nfalse () { return new (alloc()) object_false(); }
50        object_u8*     nu8    (uint8_t  v) { return new (alloc()) object_u8(v);     }
51        object_u16*    nu16   (uint16_t v) { return new (alloc()) object_u16(v);    }
52        object_u32*    nu32   (uint32_t v) { return new (alloc()) object_u32(v);    }
53        object_u64*    nu64   (uint64_t v) { return new (alloc()) object_u64(v);    }
54        object_i8*     ni8    (int8_t   v) { return new (alloc()) object_i8(v);     }
55        object_i16*    ni16   (int16_t  v) { return new (alloc()) object_i16(v);    }
56        object_i32*    ni32   (int32_t  v) { return new (alloc()) object_i32(v);    }
57        object_i64*    ni64   (int64_t  v) { return new (alloc()) object_i64(v);    }
58        object_float*  nfloat (float    v) { return new (alloc()) object_float(v);  }
59        object_double* ndouble(double   v) { return new (alloc()) object_double(v); }
60
61        object_raw_ref* nraw_ref(void* ptr, uint32_t len)
62                { return new (alloc()) object_raw_ref(ptr, len); }
63
64        object_const_raw_ref* nraw_ref(const void* ptr, uint32_t len)
65                { return new (alloc()) object_const_raw_ref(ptr, len); }
66
67        object_raw_ref* nraw_copy(const void* ptr, uint32_t len)
68                {
69                        void* copy = malloc(len);
70                        if(!copy) { throw std::bad_alloc(); }
71                        object_raw_ref* o;
72                        try {
73                                o = new (alloc()) object_raw_ref(copy, len);
74                                push_finalizer<void>(&zone::finalize_free, NULL, copy);
75                        } catch (...) {
76                                free(copy);
77                                throw;
78                        }
79                        memcpy(copy, ptr, len);
80                        return o;
81                }
82
83        object_array* narray()
84                { return new (alloc()) object_array(); }
85
86        object_array* narray(size_t reserve_size)
87                { return new (alloc()) object_array(reserve_size); }
88
89        object_map* nmap()
90                { return new (alloc()) object_map(); }
91
92<% GENERATION_SIZE = 16 %>
93<% 1.upto(GENERATION_SIZE) {|i| %>
94        object_array* narray(<% 1.upto(i-1) {|n| %>object o<%=n%>, <% } %>object o<%=i%>)
95                { object_array* a = new (alloc()) object_array(<%=i%>);
96                        <% 1.upto(i) {|n| %>a->push_back(o<%=n%>);
97                        <% } %>return a; }
98<% } %>
99
100<% 1.upto(GENERATION_SIZE) {|i| %>
101        object_map* nmap(<% 1.upto(i-1) {|n| %>object k<%=n%>, object v<%=n%>, <% } %>object k<%=i%>, object v<%=i%>)
102                { object_map* m = new (alloc()) object_map();
103                        <% 1.upto(i) {|n| %>m->store(k<%=n%>, v<%=n%>);
104                        <% } %>return m; }
105<% } %>
106
107public:
108        void clear();
109        bool empty() const;
110
111private:
112        void* alloc();
113
114private:
115        size_t m_used;
116
117        static const size_t MAX_OBJECT_SIZE =
118                sizeof(object_raw_ref) > sizeof(object_array)
119                        ? ( sizeof(object_raw_ref) > sizeof(object_map)
120                                        ? sizeof(object_raw_ref)
121                                        : sizeof(object_map)
122                          )
123                        : ( sizeof(object_array) > sizeof(object_map)
124                                        ? sizeof(object_array)
125                                        : sizeof(object_map)
126                          )
127                ;
128
129        struct cell_t {
130                char data[MAX_OBJECT_SIZE];
131        };
132
133        typedef std::vector<cell_t*> pool_t;
134        pool_t m_pool;
135
136
137        class finalizer {
138        public:
139                finalizer(void (*func)(void*, void*), void* obj, void* user) :
140                        m_obj(obj), m_user(user), m_func(func) {}
141                void call() { (*m_func)(m_obj, m_user); }
142        private:
143                void* m_obj;
144                void* m_user;
145                void (*m_func)(void*, void*);
146        };
147
148        typedef std::vector<finalizer> user_finalizer_t;
149        user_finalizer_t m_user_finalizer;
150
151private:
152        void expand_chunk();
153
154public:
155        static void finalize_free(void* obj, void* user)
156                { free(user); }
157
158private:
159        zone(const zone&);
160};
161
162
163template <typename T>
164inline void zone::push_finalizer(void (*func)(void* obj, void* user), T* obj, void* user)
165{
166        m_user_finalizer.push_back( finalizer(
167                        func, reinterpret_cast<void*>(obj),
168                        user) );
169}
170
171inline bool zone::empty() const
172{
173        return m_used == 0 && m_user_finalizer.empty();
174}
175
176inline void* zone::alloc()
177{
178        if(m_pool.size() <= m_used/ZONE_CHUNK_SIZE) {
179                expand_chunk();
180        }
181        void* data = m_pool[m_used/ZONE_CHUNK_SIZE][m_used%ZONE_CHUNK_SIZE].data;
182        ++m_used;
183        return data;
184}
185
186
187}  // namespace msgpack
188
189#endif /* msgpack/zone.hpp */
190
Note: See TracBrowser for help on using the browser.